2 #include <event2/event.h>
11 #include <trp_internal.h>
13 /* connections and sets of connections */
14 TRPS_CONNECTION *trps_connection_new(TALLOC_CTX *mem_ctx)
16 TRPS_CONNECTION *new_conn=talloc_new(mem_ctx, TRPS_CONNECTION);
18 if (new_conn != NULL) {
28 TRPS_CONNECTION_SET *trps_connection_set_new(TALLOC_CTX *mem_ctx)
30 TRPS_CONNECTION_SET *new_set=talloc_new(mem_ctx, TRPS_CONNECTION_SET);
33 if (new_set != NULL) {
35 for(ii=0; ii<TRPS_CONNECTIONS_MAX; ii++)
42 TRPS_ERR trps_connection_set_add(TRPS_CONNECTION_SET *tcs, TRPS_CONNECTION *new_conn)
44 TR_ERR err=TRPS_ERR_OK;
46 if (tcs->nconn < TRPS_CONNECTIONS_MAX) {
47 tcs->conn[tcs->nconn]=new_conn;
48 talloc_steal(tcs, new_conn);
51 err=TRPS_ERR_MAX_CONN;
57 int trps_connection_set_del(TRPS_CONNECTION_SET *tcs, TRPS_CONNECTION *conn)
60 return TRPS_ERR_UNKNOWN;
63 int trps_connection_set_len(TRPS_CONNECTION_SET *tcs)
71 TRPS_INSTANCE *trps_create (TALLOC_CTX *mem_ctx)
73 return talloc_zero(mem_ctx, TRPS_INSTANCE);
76 void trps_destroy (TRPS_INSTANCE *trps)
83 int trps_send_msg (TRPS_INSTANCE *trps,
86 const char *msg_content)
91 /* Send the request over the connection */
92 if (err = gsscon_write_encrypted_token (conn,
95 strlen(msg_content))) {
96 tr_err( "trps_send_msg: Error sending message over connection.\n");
103 static int trps_listen (TRPS_INSTANCE *trps, int port)
110 struct sockaddr_storage storage;
111 struct sockaddr_in in4;
114 struct sockaddr_in *saddr = (struct sockaddr_in *) &addr.in4;
116 saddr->sin_port = htons (port);
117 saddr->sin_family = AF_INET;
118 saddr->sin_addr.s_addr = INADDR_ANY;
120 if (0 > (conn = socket (AF_INET, SOCK_STREAM, 0)))
123 setsockopt(conn, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
125 if (0 > (rc = bind (conn, (struct sockaddr *) saddr, sizeof(struct sockaddr_in))))
128 if (0 > (rc = listen(conn, 512)))
131 tr_debug("trps_listen: TRP Server listening on port %d", port);
135 /* returns EACCES if authorization is denied */
136 static int trps_auth_cb(gss_name_t clientName, gss_buffer_t displayName,
139 TRPS_INSTANCE *inst = (TRPS_INSTANCE *)data;
140 TR_NAME name ={(char *) displayName->value,
141 displayName->length};
144 if (0!=inst->auth_handler(clientName, &name, inst->cookie)) {
145 tr_debug("trps_auth_cb: client '%.*s' denied authorization.", name.len, name.buf);
146 result=EACCES; /* denied */
152 /* returns 0 on authorization success, 1 on failure, or -1 in case of error */
153 static int trps_auth_connection (TRPS_INSTANCE *inst,
155 gss_ctx_id_t *gssctx)
158 int auth, autherr = 0;
159 gss_buffer_desc nameBuffer = {0, NULL};
163 nameLen = asprintf(&name, "trustrouter@%s", inst->hostname);
164 nameBuffer.length = nameLen;
165 nameBuffer.value = name;
167 if (rc = gsscon_passive_authenticate(conn, nameBuffer, gssctx, trps_auth_cb, inst)) {
168 tr_debug("trps_auth_connection: Error from gsscon_passive_authenticate(), rc = %d.", rc);
172 if (rc = gsscon_authorize(*gssctx, &auth, &autherr)) {
173 tr_debug("trps_auth_connection: Error from gsscon_authorize, rc = %d, autherr = %d.",
179 tr_debug("trps_auth_connection: Connection authenticated, conn = %d.", conn);
181 tr_debug("trps_auth_connection: Authentication failed, conn %d.", conn);
186 static int trps_read_message (TRPS_INSTANCE *trps, int conn, gss_ctx_id_t *gssctx, char **msg)
192 if (err = gsscon_read_encrypted_token(conn, *gssctx, &buf, &buflen)) {
198 tr_debug("trps_read_request(): Request Received, %u bytes.", (unsigned) buflen);
199 tr_debug("trps_read_request(): %.*s", buflen, buf);
201 *msg=talloc_strndup(NULL, buf, buflen); /* no context owns this! */
206 static int trps_get_listener(TRPS_INSTANCE *trps,
207 TRPS_REQ_FUNC *req_handler,
208 trps_auth_func *auth_handler,
209 const char *hostname,
215 if (0 > (listen = trps_listen(trps, port))) {
217 if (0 == strerror_r(errno, errbuf, 256)) {
218 tr_debug("trps_get_listener: Error opening port %d: %s.", port, errbuf);
220 tr_debug("trps_get_listener: Unknown error openining port %d.", port);
225 /* opening port succeeded */
226 tr_debug("trps_get_listener: Opened port %d.", port);
228 /* make this socket non-blocking */
229 if (0 != fcntl(listen, F_SETFL, O_NONBLOCK)) {
230 tr_debug("trps_get_listener: Error setting O_NONBLOCK.");
237 /* store the caller's request handler & cookie */
238 trps->req_handler = req_handler;
239 trps->auth_handler = auth_handler;
240 trps->hostname = talloc_strdup(trps, hostname);
242 trps->cookie = cookie;
249 /* Accept and process a connection on a port opened with trps_get_listener().
250 * Returns the socket FD, or -1 in case of error. */
251 int trps_accept(TRPS_INSTANCE *trps, int listen)
253 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
256 TRPS_CONNECTION *trps_conn=0;
257 TRPS_ERR trps_err=TRPS_ERR_OK;
259 conn = accept(listen, NULL, NULL);
262 perror("Error from TRP Server accept()");
266 /* establish a GSS context */
267 if (trps_auth_connection(trps, conn, &gssctx)) {
268 tr_notice("trps_accept: Error authorizing TID Server connection.");
269 close(conn); /* did not work */
274 tr_notice("trps_accept: Connection authorized!");
276 /* add this to the list of connections */
277 trps_conn=trps_connection_new(tmp_ctx);
278 if (trps_conn==NULL) {
279 tr_debug("trps_handle_connection: Could not allocate TRPS connection.");
285 trps_err=trps_connection_set_add(trps->connections, trps_conn); /* handles talloc steal */
286 if (trps_err != TRPS_ERR_OK) {
287 tr_debug("trps_handle_connection: Error adding connection to set (trps_err=%d)", trps_err);
293 /* GSS context established, saved to the TRPS instance---success! */
296 talloc_free(tmp_ctx);
304 static gss_ctx_id_t trps_establish_gss_context (TRPS_INSTANCE *trps, int conn)
306 TALLOC_CTX *tmp_ctx=talloc_new(NULL);
307 gss_ctx_id_t gssctx = GSS_C_NO_CONTEXT;
312 if (trps_auth_connection(trps, conn, &gssctx))
313 tr_notice("trps_establish_gss_context: Error authorizing TID Server connection.");
315 tr_notice("trps_establish_gss_context: Connection authorized!");
318 msg_len = trps_read_message(trps, conn, &gssctx, &msg_rec);
319 talloc_steal(tmp_ctx, msg_rec); /* get this in our context */
321 tr_debug("trps_handle_connection: Error from trps_read_message()");
325 tr_debug("trps_handle_connection: msg_len=%d", msg_len);
326 reply=talloc_asprintf(tmp_ctx, "TRPS heard: %.*s", msg_len, msg_rec);
327 if (0 > (rc = trps_send_msg(trps, conn, gssctx, reply))) {
328 tr_debug("trps_handle_connection: Error from trps_send_message(), rc = %d.", rc);
332 talloc_free(tmp_ctx);