Successful messages via mq to main thread.
[trust_router.git] / trp / trps.c
1 #include <fcntl.h>
2 #include <event2/event.h>
3 #include <talloc.h>
4 #include <errno.h>
5 #include <unistd.h>
6
7 #include <gsscon.h>
8 #include <tr_rp.h>
9 #include <tr_event.h>
10 #include <tr_debug.h>
11 #include <trp_internal.h>
12
13
14 TRPS_INSTANCE *trps_new (TALLOC_CTX *mem_ctx)
15 {
16   TRPS_INSTANCE *trps=talloc(mem_ctx, TRPS_INSTANCE);
17   if (trps!=NULL)  {
18     trps->hostname=NULL;
19     trps->port=0;
20     trps->cookie=NULL;
21     trps->conn=NULL;
22     trps->mq=tr_mq_new(trps);
23     if (trps->mq==NULL) {
24       /* failed to allocate mq */
25       talloc_free(trps);
26       trps=NULL;
27     }
28   }
29   return trps;
30 }
31
32 void trps_free (TRPS_INSTANCE *trps)
33 {
34   if (trps!=NULL)
35     talloc_free(trps);
36 }
37
38 TR_MQ_MSG *trps_mq_pop(TRPS_INSTANCE *trps)
39 {
40   return tr_mq_pop(trps->mq);
41 }
42
43 void trps_mq_append(TRPS_INSTANCE *trps, TR_MQ_MSG *msg)
44 {
45   tr_mq_append(trps->mq, msg);
46 }
47
48 /* stand-in for a function that finds the connection for a particular peer */
49 #if 0
50 static TRP_CONNECTION *trps_find_connection(TRPS_INSTANCE *trps)
51 {
52   return trps->conn;
53 }
54 #endif
55
56 void trps_add_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *new)
57 {
58   if (trps->conn==NULL)
59     trps->conn=new;
60   else
61     trp_connection_append(trps->conn, new);
62
63   talloc_steal(trps, new);
64 }
65
66 int trps_send_msg (TRPS_INSTANCE *trps,
67                    int conn,
68                    gss_ctx_id_t gssctx,
69                    const char *msg_content)
70 {
71   int err=0;
72   int rc=0;
73
74   /* Send the request over the connection */
75   if (err = gsscon_write_encrypted_token (conn,
76                                           gssctx,
77                                           msg_content, 
78                                           strlen(msg_content))) {
79     tr_err( "trps_send_msg: Error sending message over connection.\n");
80     rc = -1;
81   }
82
83   return rc;
84 }
85
86 static int trps_listen (TRPS_INSTANCE *trps, int port) 
87 {
88     int rc = 0;
89     int conn = -1;
90     int optval = 1;
91
92     union {
93       struct sockaddr_storage storage;
94       struct sockaddr_in in4;
95     } addr;
96
97     struct sockaddr_in *saddr = (struct sockaddr_in *) &addr.in4;
98
99     saddr->sin_port = htons (port);
100     saddr->sin_family = AF_INET;
101     saddr->sin_addr.s_addr = INADDR_ANY;
102
103     if (0 > (conn = socket (AF_INET, SOCK_STREAM, 0)))
104       return conn;
105
106     setsockopt(conn, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
107
108     if (0 > (rc = bind (conn, (struct sockaddr *) saddr, sizeof(struct sockaddr_in))))
109       return rc;
110
111     if (0 > (rc = listen(conn, 512)))
112       return rc;
113
114     tr_debug("trps_listen: TRP Server listening on port %d", port);
115     return conn;
116 }
117
118 /* returns EACCES if authorization is denied */
119 int trps_auth_cb(gss_name_t clientName, gss_buffer_t displayName, void *data)
120 {
121   TRPS_INSTANCE *inst = (TRPS_INSTANCE *)data;
122   int result=0;
123
124   if (0!=inst->auth_handler(clientName, displayName, inst->cookie)) {
125     tr_debug("trps_auth_cb: client '%.*s' denied authorization.", displayName->length, displayName->value);
126     result=EACCES; /* denied */
127   }
128
129   return result;
130 }
131
132 #if 0
133 static int trps_read_message (TRPS_INSTANCE *trps, int conn, gss_ctx_id_t *gssctx, char **msg)
134 {
135   int err;
136   char *buf;
137   size_t buflen = 0;
138
139   if (err = gsscon_read_encrypted_token(conn, *gssctx, &buf, &buflen)) {
140     if (buf)
141       free(buf);
142     return -1;
143   }
144
145   tr_debug("trps_read_request(): Request Received, %u bytes.", (unsigned) buflen);
146   tr_debug("trps_read_request(): %.*s", buflen, buf);
147
148   *msg=talloc_strndup(NULL, buf, buflen); /* no context owns this! */
149   free(buf);
150   return buflen;
151 }
152 #endif
153
154 int trps_get_listener(TRPS_INSTANCE *trps,
155                       TRP_REQ_FUNC req_handler,
156                       TRP_AUTH_FUNC auth_handler,
157                       const char *hostname,
158                       unsigned int port,
159                       void *cookie)
160 {
161   int listen = -1;
162
163   if (0 > (listen = trps_listen(trps, port))) {
164     char errbuf[256];
165     if (0 == strerror_r(errno, errbuf, 256)) {
166       tr_debug("trps_get_listener: Error opening port %d: %s.", port, errbuf);
167     } else {
168       tr_debug("trps_get_listener: Unknown error openining port %d.", port);
169     }
170   } 
171
172   if (listen > 0) {
173     /* opening port succeeded */
174     tr_debug("trps_get_listener: Opened port %d.", port);
175     
176     /* make this socket non-blocking */
177     if (0 != fcntl(listen, F_SETFL, O_NONBLOCK)) {
178       tr_debug("trps_get_listener: Error setting O_NONBLOCK.");
179       close(listen);
180       listen=-1;
181     }
182   }
183
184   if (listen > 0) {
185     /* store the caller's request handler & cookie */
186     trps->req_handler = req_handler;
187     trps->auth_handler = auth_handler;
188     trps->hostname = talloc_strdup(trps, hostname);
189     trps->port = port;
190     trps->cookie = cookie;
191   }
192
193   return listen;
194 }
195
196 /* old cruft */
197 #if 0
198 static gss_ctx_id_t trps_establish_gss_context (TRPS_INSTANCE *trps, int conn)
199 {
200   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
201   gss_ctx_id_t gssctx = GSS_C_NO_CONTEXT;
202   char *msg_rec=NULL;
203   int msg_len = 0;
204   int rc=0;
205
206   if (trps_auth_connection(trps, conn, &gssctx))
207     tr_notice("trps_establish_gss_context: Error authorizing TID Server connection.");
208   else:
209     tr_notice("trps_establish_gss_context: Connection authorized!");
210   return gssctx;
211
212   msg_len = trps_read_message(trps, conn, &gssctx, &msg_rec);
213   talloc_steal(tmp_ctx, msg_rec); /* get this in our context */
214   if (0 > msg_len) {
215     tr_debug("trps_handle_connection: Error from trps_read_message()");
216     goto cleanup;
217   }
218   
219   tr_debug("trps_handle_connection: msg_len=%d", msg_len);
220   reply=talloc_asprintf(tmp_ctx, "TRPS heard: %.*s", msg_len, msg_rec);
221   if (0 > (rc = trps_send_msg(trps, conn, gssctx, reply))) {
222     tr_debug("trps_handle_connection: Error from trps_send_message(), rc = %d.", rc);
223   }
224
225 cleanup:
226   talloc_free(tmp_ctx);
227   return conn;
228 }
229 #endif