Branch data Line data Source code
1 : : /* zxidhrxmlwsp.c - ID-SIS HR-XML WSP
2 : : * Copyright (c) 2007-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.
3 : : * Author: Sampo Kellomaki (sampo@iki.fi)
4 : : * This is confidential unpublished proprietary source code of the author.
5 : : * NO WARRANTY, not even implied warranties. Contains trade secrets.
6 : : * Distribution prohibited unless authorized in writing.
7 : : * Licensed under Apache License 2.0, see file COPYING.
8 : : * $Id: zxidhrxmlwsp.c,v 1.14 2009-11-29 12:23:06 sampo Exp $
9 : : *
10 : : * 19.6.2007, created --Sampo
11 : : *
12 : : * See also: http://hoohoo.ncsa.uiuc.edu/cgi/interface.html (CGI specification)
13 : : * README-zxid, section 10 "zxid_simple() API"
14 : : */
15 : :
16 : : #include "platform.h"
17 : :
18 : : #include <string.h>
19 : : #include <stdio.h>
20 : : #include <stdlib.h>
21 : :
22 : : #include <sys/types.h>
23 : : #include <sys/stat.h>
24 : : #include <fcntl.h>
25 : :
26 : : #include <zx/errmac.h>
27 : : #include <zx/zxid.h> /* ZXID main API, including zxid_simple(). */
28 : : #include <zx/zxidutil.h>
29 : : #include <zx/zxidconf.h> /* Default and compile-time configuration options. */
30 : : #include <zx/wsf.h>
31 : : #include <zx/c/zxidvers.h>
32 : : #include <zx/c/zx-ns.h>
33 : : #include <zx/c/zx-data.h>
34 : :
35 : : char* help =
36 : : "zxidhrxmlwsp - SAML 2.0 WSP CGI - R" ZXID_REL "\n\
37 : : SAML 2.0 is a standard for federated identity and Single Sign-On.\n\
38 : : Copyright (c) 2007-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.\n\
39 : : Author: Sampo Kellomaki (sampo@iki.fi)\n\
40 : : NO WARRANTY, not even implied warranties. Licensed under Apache License v2.0\n\
41 : : See http://www.apache.org/licenses/LICENSE-2.0\n\
42 : : Send well-researched bug reports to the author. Home: zxid.org\n\
43 : : \n\
44 : : Usage: zxidhrxmlwsp [options] (when used as CGI, no options can be supplied)\n\
45 : : -h This help message\n\
46 : : -- End of options\n";
47 : :
48 : : /* ============== M A I N ============== */
49 : :
50 : : #define ZXIDHLO "zxidhrxmlwsp"
51 : : #define CONF "PATH=/var/zxid/"
52 : :
53 : : /* Called by: */
54 : : int main(int argc, char** argv)
55 : 9 : {
56 : : struct zx_ctx ctx;
57 : : zxid_conf cfs;
58 : : zxid_conf* cf;
59 : : zxid_ses sess;
60 : 9 : zxid_ses* ses = &sess;
61 : : struct zx_root_s* r;
62 : : //struct zx_e_Envelope_s* env;
63 : : //zxid_epr* epr;
64 : : struct zx_str* ss;
65 : : //char* sid;
66 : : char* nid;
67 : : char* p;
68 : : char* res;
69 : : char buf[256*1024]; /* *** should figure the size dynamically */
70 : : char urlbuf[256];
71 : 9 : int got, fd, cl=0;
72 : : char* qs;
73 : : char* qs2;
74 : 9 : ZERO(ses, sizeof(zxid_ses));
75 : :
76 : : #if 1
77 : : /* Helps debugging CGI scripts if you see stderr. */
78 : 9 : close(2);
79 [ - + ]: 9 : if (open("/var/tmp/zxid.stderr", O_WRONLY | O_CREAT | O_APPEND, 0666) != 2)
80 : 0 : exit(2);
81 : 9 : fprintf(stderr, "=================== Running idhrxml wsp ===================\n");
82 : 9 : zx_debug = 2;
83 : : #endif
84 : : #if 1
85 : 9 : strncpy(zx_instance, "\t\e[45mhrxml_wsp\e[0m", sizeof(zx_instance));
86 : : #else
87 : : strncpy(zx_instance, "\thrxml_wsp", sizeof(zx_instance));
88 : : #endif
89 : :
90 : 9 : qs = getenv("CONTENT_LENGTH");
91 [ + + ]: 9 : if (qs)
92 : 7 : sscanf(qs, "%d", &cl);
93 : :
94 [ + + ]: 9 : if (cl) {
95 : 7 : read_all_fd(0, buf, MIN(cl, sizeof(buf)-1), &got);
96 : 7 : buf[got] = 0;
97 : 7 : qs2 = buf;
98 : : } else {
99 : 2 : qs2 = getenv("QUERY_STRING");
100 [ + + ]: 2 : if (!qs2)
101 : 1 : qs2 = "";
102 : 2 : cl = strlen(qs2);
103 : : }
104 : 9 : qs = strdup(qs2);
105 : 9 : D_XML_BLOB(0, "HRXML IN", -2, qs);
106 : :
107 [ + + ]: 9 : if (argc > 1) {
108 : 1 : fprintf(stderr, "This is a CGI script (written in C). No arguments are accepted.\n%s", help);
109 : 1 : exit(1);
110 : : }
111 : :
112 : : #if 1
113 : 8 : zx_reset_ctx(&ctx);
114 : 8 : ZERO(&cfs, sizeof(cfs));
115 : 8 : cfs.ctx = &ctx;
116 : 8 : cf = &cfs;
117 : 8 : zxid_conf_to_cf_len(cf, -1, CONF);
118 : : #else
119 : : cf = zxid_new_conf_to_cf(CONF);
120 : : #endif
121 : :
122 : : /* Dynamic construction of URL configuration parameter */
123 : :
124 : : #if 0
125 : : #define PROTO_STR "https://"
126 : : #else
127 : : #define PROTO_STR "http://"
128 : : #endif
129 : :
130 : 8 : strcpy(urlbuf, PROTO_STR);
131 : 8 : p = urlbuf + sizeof(PROTO_STR)-1;
132 : 8 : res = getenv("HTTP_HOST");
133 [ + + ]: 8 : if (res) {
134 : 7 : strcpy(p, res);
135 : 7 : p+=strlen(res);
136 : : }
137 : 8 : res = getenv("SCRIPT_NAME");
138 [ + + ]: 8 : if (res) {
139 : 7 : strcpy(p, res);
140 : 7 : p+=strlen(res);
141 : : }
142 [ - + ]: 8 : if (p > urlbuf + sizeof(urlbuf))
143 : 0 : exit(1);
144 : 8 : zxid_url_set(cf, urlbuf);
145 : :
146 : : //if (!memcmp(qs+cl-4, "?o=B", 4)) {
147 [ + + ]: 8 : if (!memcmp(qs, "o=B", 3)) {
148 [ + - - + ]: 1 : D("Metadata qs(%s)", qs);
149 : : //cf = zxid_new_conf_to_cf(CONF);
150 : :
151 : 1 : res = zxid_simple_cf(cf, cl, qs, 0, 0x1fff);
152 [ # # ]: 0 : switch (res[0]) {
153 : : default:
154 : 0 : ERR("Unknown zxid_simple() response(%s)", res);
155 : : case 'd': break; /* Logged in case */
156 : : }
157 : 0 : ERR("Not a metadata qs(%s)",qs);
158 : 0 : exit(1);
159 : : }
160 : :
161 : 7 : nid = zxid_wsp_validate(cf, ses, 0, buf);
162 [ - + ]: 7 : if (!nid) {
163 : : DD("Request validation failed buf(%.*s)", got, buf);
164 : 0 : ERR("Request validation failed len=%d", got);
165 : 0 : ss = zxid_wsp_decorate(cf, ses, 0, "<Response><lu:Status code=\"INV\" comment=\"Request validation failed. Replay?\"></lu:Status></Response>");
166 : : DD("ss(%.*s)", ss->len, ss->s);
167 : 0 : printf("CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
168 : 0 : exit(1);
169 : : }
170 [ + - - + ]: 7 : D("Target nid(%s)", nid);
171 : :
172 : 7 : r = zx_dec_zx_root(cf->ctx, cl, qs2, "hrxml wsp");
173 : :
174 : : DD("Decoded nid(%s)", nid);
175 : :
176 [ + - - + ]: 7 : if (!r || !r->Envelope) {
177 : 0 : ERR("No SOAP Envelope found buf(%.*s)", got, buf);
178 : 0 : exit(1);
179 : : }
180 [ - + ]: 7 : if (!r->Envelope->Body) {
181 : 0 : ERR("No SOAP Body found buf(%.*s)", got, buf);
182 : 0 : exit(1);
183 : : }
184 : :
185 [ + + ]: 7 : if (r->Envelope->Body->idhrxml_Create) {
186 [ + - - + ]: 1 : D("Create %d",0);
187 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Create->CreateItem) {
188 : 0 : ERR("No CreateItem found buf(%.*s)", got, buf);
189 : 0 : exit(1);
190 : : }
191 : :
192 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Create->CreateItem->NewData) {
193 : 0 : ERR("No NewData found buf(%.*s)", got, buf);
194 : 0 : exit(1);
195 : : }
196 : :
197 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Create->CreateItem->NewData->Candidate) {
198 : 0 : ERR("No Candidate found buf(%.*s)", got, buf);
199 : : #if 0
200 : : env = ZXID_RESP_ENV(cf, "idhrxml:CreateResponse", "Fail", "NewData does not contain Candidate element.");
201 : : ss = zx_EASY_ENC_SO_e_Envelope(cf->ctx, env);
202 : : #else
203 : 0 : ss = zxid_wsp_decorate(cf, ses, 0, "<idhrxml:CreateResponse><lu:Status code=\"Fail\" comment=\"NewData does not contain Candidate element.\"></lu:Status></idhrxml:CreateResponse>");
204 : : #endif
205 : 0 : printf("CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
206 : 0 : return 0;
207 : : }
208 : :
209 : 1 : ss = zx_easy_enc_elem_opt(cf, &r->Envelope->Body->idhrxml_Create->CreateItem->NewData->Candidate->gg);
210 : :
211 : 1 : fd = open_fd_from_path(O_CREAT|O_WRONLY|O_TRUNC, 0666, "create", 1, "%shrxml/cv.xml", cf->path);
212 : 1 : write_all_fd(fd, ss->s, ss->len);
213 : 1 : close_file(fd, (const char*)__FUNCTION__);
214 : :
215 : : #if 0
216 : : env = ZXID_RESP_ENV(cf, "idhrxml:CreateResponse", "OK", "Fine");
217 : : D("HERE(%p)", env);
218 : : ss = zx_EASY_ENC_SO_e_Envelope(cf->ctx, env);
219 : : D("HERE(%p)", ss);
220 : : #else
221 : 1 : ss = zxid_wsp_decorate(cf, ses, 0, "<idhrxml:CreateResponse><lu:Status code=\"OK\" comment=\"Fine\"></lu:Status></idhrxml:CreateResponse>");
222 : : #endif
223 : 1 : printf("CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
224 [ + - - + ]: 1 : D("ss(%.*s)", ss->len, ss->s);
225 : 1 : return 0;
226 : : }
227 : :
228 [ + + ]: 6 : if (r->Envelope->Body->idhrxml_Query) {
229 [ + - - + ]: 1 : D("Query %d",0);
230 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Query->QueryItem) {
231 : 0 : ERR("No QueryItem found buf(%.*s)", got, buf);
232 : 0 : exit(1);
233 : : }
234 : :
235 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Query->QueryItem->Select) {
236 : 0 : ERR("No Select found buf(%.*s)", got, buf);
237 : 0 : exit(1);
238 : : }
239 : :
240 : : /* *** This mock implementation does not actually interpret the Select string. */
241 : :
242 : : /* Parse the XML from the CV file into data structure and include it as Candidate. */
243 : :
244 : 1 : got = read_all(sizeof(buf), buf, "query", 1, "%shrxml/cv.xml", cf->path);
245 [ - + ]: 1 : if (got < 1) {
246 : 0 : ERR("Reading hrxml/cv.xml resulted in error or the file was empty. ret=%d", got);
247 : : #if 0
248 : : env = ZXID_RESP_ENV(cf, "idhrxml:QueryResponse", "Fail", "Empty or no data");
249 : : ss = zx_EASY_ENC_SO_e_Envelope(cf->ctx, env);
250 : : #else
251 : 0 : ss = zxid_wsp_decorate(cf, ses, 0, "<idhrxml:QueryResponse><lu:Status code=\"Fail\" comment=\"Empty or no data\"></lu:Status></idhrxml:QueryResponse>");
252 : : #endif
253 : 0 : printf("CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
254 : 0 : return 0;
255 : : }
256 : :
257 : 1 : r = zx_dec_zx_root(cf->ctx, got, buf, "hrxml wsp cand");
258 [ + - - + ]: 1 : if (!r || !r->Candidate) {
259 : 0 : ERR("No hrxml:Candidate tag found in cv.xml(%s)", buf);
260 : : #if 0
261 : : env = ZXID_RESP_ENV(cf, "idhrxml:QueryResponse", "Fail", "No Candidate in data");
262 : : ss = zx_EASY_ENC_SO_e_Envelope(cf->ctx, env);
263 : : #else
264 : 0 : ss = zxid_wsp_decorate(cf, ses, 0, "<idhrxml:QueryResponse><lu:Status code=\"Fail\" comment=\"No Candidate in data.\"></lu:Status></idhrxml:QueryResponse>");
265 : : #endif
266 : 0 : printf("CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
267 : 0 : return 0;
268 : : }
269 : :
270 : : #if 0
271 : : env = ZXID_RESP_ENV(cf, "idhrxml:QueryResponse", "OK", "Fine");
272 : : env->Body->idhrxml_QueryResponse->Data = zx_NEW_idhrxml_Data(cf->ctx,0);
273 : : env->Body->idhrxml_QueryResponse->Data->Candidate = r->Candidate;
274 : : ss = zx_EASY_ENC_SO_e_Envelope(cf->ctx, env);
275 : : #else
276 : 1 : ss = zxid_wsp_decoratef(cf, ses, 0, "<idhrxml:QueryResponse><lu:Status code=\"OK\" comment=\"Fine\"></lu:Status><idhrxml:Data><idhrxml:Candidate>%s</idhrxml:Candidate></idhrxml:Data></idhrxml:QueryResponse>", buf);
277 : : #endif
278 : 1 : printf("CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
279 : 1 : return 0;
280 : : }
281 : :
282 : : // Modify
283 : :
284 [ + + ]: 5 : if (r->Envelope->Body->idhrxml_Modify) {
285 [ + - - + ]: 1 : D("Modify %d",0);
286 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Modify->ModifyItem) {
287 : 0 : ERR("No ModifyItem found buf(%.*s)", got, buf);
288 : 0 : exit(1);
289 : : }
290 : :
291 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Modify->ModifyItem->Select) {
292 : 0 : ERR("No Select found buf(%.*s)", got, buf);
293 : : //exit(1);
294 : : }
295 : :
296 : : /* *** This mock implementation does not actually interpret the Select string. */
297 : :
298 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Modify->ModifyItem->NewData) {
299 : 0 : ERR("No NewData found buf(%.*s)", got, buf);
300 : 0 : exit(1);
301 : : }
302 : :
303 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Modify->ModifyItem->NewData->Candidate) {
304 : 0 : ERR("No Candidate found buf(%.*s)", got, buf);
305 : : #if 0
306 : : env = ZXID_RESP_ENV(cf, "idhrxml:ModifyResponse", "Fail", "NewData does not contain Candidate element.");
307 : : ss = zx_EASY_ENC_SO_e_Envelope(cf->ctx, env);
308 : : #else
309 : 0 : ss = zxid_wsp_decorate(cf, ses, 0, "<idhrxml:ModifyResponse><lu:Status code=\"Fail\" comment=\"No Candidate in data.\"></lu:Status></idhrxml:ModifyResponse>");
310 : : #endif
311 : 0 : printf("CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
312 : 0 : return 0;
313 : : }
314 : :
315 : 1 : ss = zx_easy_enc_elem_opt(cf, &r->Envelope->Body->idhrxml_Modify->ModifyItem->NewData->Candidate->gg);
316 : :
317 : 1 : fd = open_fd_from_path(O_CREAT|O_WRONLY|O_TRUNC, 0666, "modify", 1, "%shrxml/cv.xml", cf->path);
318 : 1 : write_all_fd(fd, ss->s, ss->len);
319 : 1 : close_file(fd, (const char*)__FUNCTION__);
320 : :
321 : : #if 0
322 : : env = ZXID_RESP_ENV(cf, "idhrxml:ModifyResponse", "OK", "Fine");
323 : : ss = zx_EASY_ENC_SO_e_Envelope(cf->ctx, env);
324 : : #else
325 : 1 : ss = zxid_wsp_decorate(cf, ses, 0, "<idhrxml:ModifyResponse><lu:Status code=\"OK\" comment=\"Fine\"></lu:Status></idhrxml:ModifyResponse>");
326 : : #endif
327 [ + - - + ]: 1 : D("ss(%.*s)", ss->len, ss->s);
328 : 1 : printf("CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
329 : 1 : return 0;
330 : : }
331 : :
332 : : // Delete
333 : :
334 [ + + ]: 4 : if (r->Envelope->Body->idhrxml_Delete) {
335 [ + - - + ]: 1 : D("Delete %d",0);
336 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Delete->DeleteItem) {
337 : 0 : ERR("No DeleteItem found buf(%.*s)", got, buf);
338 : 0 : exit(1);
339 : : }
340 : :
341 [ - + ]: 1 : if (!r->Envelope->Body->idhrxml_Delete->DeleteItem->Select) {
342 : 0 : ERR("No Select found buf(%.*s)", got, buf);
343 : : //exit(1);
344 : : }
345 : :
346 : : /* *** This mock implementation does not actually interpret the Select string. */
347 : :
348 : 1 : got = name_from_path(buf, sizeof(buf), "%shrxml/cv.xml", cf->path);
349 : 1 : unlink(buf);
350 : :
351 : : #if 0
352 : : env = ZXID_RESP_ENV(cf, "idhrxml:DeleteResponse", "OK", "Fine");
353 : : ss = zx_EASY_ENC_SO_e_Envelope(cf->ctx, env);
354 : : #else
355 : 1 : ss = zxid_wsp_decorate(cf, ses, 0, "<idhrxml:DeleteResponse><lu:Status code=\"OK\" comment=\"Fine\"></lu:Status></idhrxml:DeleteResponse>");
356 : : #endif
357 [ + - - + ]: 1 : D("ss(%.*s)", ss->len, ss->s);
358 : 1 : printf("CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
359 : 1 : return 0;
360 : : }
361 : :
362 : 3 : ss = zxid_wsp_decorate(cf, ses, 0, "<Response><lu:Status code=\"BAD\" comment=\"Unknown XML\"></lu:Status></Response>");
363 [ + - - + ]: 3 : D("ss(%.*s)", ss->len, ss->s);
364 : 3 : printf("CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
365 : 3 : return 0;
366 : : }
367 : :
368 : : /* EOF -- zxidhrxmlwsp.c */
|