Demonstration release of the principles underpinning krsd.
[krsd] / src / handler / dispatch.c
1 /*
2  * rs-serve - (c) 2013 Niklas E. Cathor
3  *
4  * This program is distributed in the hope that it will be useful,
5  * but WITHOUT ANY WARRANTY; without even the implied warranty of
6  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7  * GNU Affero General Public License for more details.
8  *
9  * You should have received a copy of the GNU Affero General Public License
10  * along with this program. If not, see <http://www.gnu.org/licenses/>.
11  */
12
13 #include "rs-serve.h"
14
15 static void add_cors_headers(evhtp_request_t *req) {
16   ADD_RESP_HEADER(req, "Access-Control-Allow-Origin", RS_ALLOW_ORIGIN);
17   ADD_RESP_HEADER(req, "Access-Control-Allow-Headers", RS_ALLOW_HEADERS);
18   ADD_RESP_HEADER(req, "Access-Control-Allow-Methods", RS_ALLOW_METHODS);
19   ADD_RESP_HEADER(req, "Access-Control-Expose-Headers", RS_EXPOSE_HEADERS);
20 }
21
22 #if 0
23 static void verify_user(evhtp_request_t *req) {
24   char *username = REQUEST_GET_USER(req);
25   uid_t uid = user_get_uid(username);
26   if(uid == -1) {
27     req->status = EVHTP_RES_NOTFOUND;
28   } else if(uid == -2) {
29     req->status = EVHTP_RES_SERVERR;
30   } else if(! UID_ALLOWED(uid)) {
31     log_info("User not allowed: %s (uid: %ld)", username, uid);
32     req->status = EVHTP_RES_NOTFOUND;
33   } else {
34     log_debug("User found: %s (uid: %ld)", username, uid);
35   }
36 }
37 #endif
38
39 void dispatch_storage(evhtp_request_t *req, void *arg) {
40   req->status = 0;
41
42   do {
43     gss_buffer_desc username = GSS_C_EMPTY_BUFFER;
44
45     // TODO: It remains to be seen if CORS works with Kerberos authentication
46     add_cors_headers(req);
47
48 #if 0
49     // validate user
50     verify_user(req);
51
52     if(req->status) break; // bail
53 #endif
54
55     // authorize request
56     if(req->method != htp_method_OPTIONS) {
57       int auth_result = authorize_request(req, &username);
58       if(auth_result == 0) {
59         log_info("Requester authenticated as %.*s.", username.length, username.value);
60       } else if(auth_result == -1) {
61         log_info("Request NOT authorized.");
62         req->status = EVHTP_RES_UNAUTH;
63       } else if(auth_result == -2) {
64         log_error("An error occured while authorizing request.");    
65         req->status = EVHTP_RES_SERVERR; 
66       }
67     }
68
69     if(req->status) break; // bail
70
71     // dispatch to storage handler
72     if(req->status == 0) {
73       switch(req->method) {
74       case htp_method_OPTIONS:
75         req->status = EVHTP_RES_NOCONTENT;
76         break;
77       case htp_method_GET:
78         req->status = storage_handle_get(req, &username);
79         break;
80       case htp_method_HEAD:
81         req->status = storage_handle_head(req, &username);
82         break;
83       case htp_method_PUT:
84         req->status = storage_handle_put(req, &username);
85         break;
86       case htp_method_DELETE:
87         req->status = storage_handle_delete(req, &username);
88         break;
89       default:
90         req->status = EVHTP_RES_METHNALLOWED;
91       }
92     }
93
94     // Cleanup username
95     if (username.value != NULL) {
96       OM_uint32 major, minor;
97       major = gss_release_buffer (&minor, &username);
98       if (major != GSS_S_COMPLETE) {
99         log_error("GSSAPI cleanup of username buffer returns error code %d and minor %d.", major, minor);
100       }
101     }
102
103   } while(0);
104
105   // send reply, if status was set
106   if(req->status) {
107     evhtp_send_reply(req, req->status);
108   }
109 }