1 | /* sample-server.c -- sample SASL server |
---|
2 | * Rob Earhart |
---|
3 | * $Id: sample-server.c,v 1.1.1.1 2002-10-13 18:00:17 ghudson Exp $ |
---|
4 | */ |
---|
5 | /* |
---|
6 | * Copyright (c) 2001 Carnegie Mellon University. All rights reserved. |
---|
7 | * |
---|
8 | * Redistribution and use in source and binary forms, with or without |
---|
9 | * modification, are permitted provided that the following conditions |
---|
10 | * are met: |
---|
11 | * |
---|
12 | * 1. Redistributions of source code must retain the above copyright |
---|
13 | * notice, this list of conditions and the following disclaimer. |
---|
14 | * |
---|
15 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
16 | * notice, this list of conditions and the following disclaimer in |
---|
17 | * the documentation and/or other materials provided with the |
---|
18 | * distribution. |
---|
19 | * |
---|
20 | * 3. The name "Carnegie Mellon University" must not be used to |
---|
21 | * endorse or promote products derived from this software without |
---|
22 | * prior written permission. For permission or any other legal |
---|
23 | * details, please contact |
---|
24 | * Office of Technology Transfer |
---|
25 | * Carnegie Mellon University |
---|
26 | * 5000 Forbes Avenue |
---|
27 | * Pittsburgh, PA 15213-3890 |
---|
28 | * (412) 268-4387, fax: (412) 268-7395 |
---|
29 | * tech-transfer@andrew.cmu.edu |
---|
30 | * |
---|
31 | * 4. Redistributions of any form whatsoever must retain the following |
---|
32 | * acknowledgment: |
---|
33 | * "This product includes software developed by Computing Services |
---|
34 | * at Carnegie Mellon University (http://www.cmu.edu/computing/)." |
---|
35 | * |
---|
36 | * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO |
---|
37 | * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
---|
38 | * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE |
---|
39 | * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
---|
40 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN |
---|
41 | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
---|
42 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
---|
43 | */ |
---|
44 | |
---|
45 | #include <config.h> |
---|
46 | #include <limits.h> |
---|
47 | #include <stdio.h> |
---|
48 | #ifdef WIN32 |
---|
49 | # include <winsock.h> |
---|
50 | __declspec(dllimport) char *optarg; |
---|
51 | __declspec(dllimport) int optind; |
---|
52 | __declspec(dllimport) int getsubopt(char **optionp, const char * const *tokens, char **valuep); |
---|
53 | #else /* WIN32 */ |
---|
54 | # include <netinet/in.h> |
---|
55 | #endif /* WIN32 */ |
---|
56 | #include <sasl.h> |
---|
57 | #include <saslutil.h> |
---|
58 | |
---|
59 | #ifdef HAVE_GETOPT_H |
---|
60 | #include <getopt.h> |
---|
61 | #endif |
---|
62 | #ifdef HAVE_UNISTD_H |
---|
63 | #include <unistd.h> |
---|
64 | #endif |
---|
65 | |
---|
66 | #ifndef HAVE_GETSUBOPT |
---|
67 | int getsubopt(char **optionp, const char * const *tokens, char **valuep); |
---|
68 | #endif |
---|
69 | |
---|
70 | static const char |
---|
71 | build_ident[] = "$Build: sample-server " PACKAGE "-" VERSION " $"; |
---|
72 | |
---|
73 | static const char *progname = NULL; |
---|
74 | static int verbose; |
---|
75 | |
---|
76 | /* Note: if this is changed, change it in samp_read(), too. */ |
---|
77 | #define SAMPLE_SEC_BUF_SIZE (2048) |
---|
78 | |
---|
79 | static const char |
---|
80 | message[] = "Come here Watson, I want you."; |
---|
81 | |
---|
82 | char buf[SAMPLE_SEC_BUF_SIZE]; |
---|
83 | |
---|
84 | static const char *bit_subopts[] = { |
---|
85 | #define OPT_MIN (0) |
---|
86 | "min", |
---|
87 | #define OPT_MAX (1) |
---|
88 | "max", |
---|
89 | NULL |
---|
90 | }; |
---|
91 | |
---|
92 | static const char *ext_subopts[] = { |
---|
93 | #define OPT_EXT_SSF (0) |
---|
94 | "ssf", |
---|
95 | #define OPT_EXT_ID (1) |
---|
96 | "id", |
---|
97 | NULL |
---|
98 | }; |
---|
99 | |
---|
100 | static const char *flag_subopts[] = { |
---|
101 | #define OPT_NOPLAIN (0) |
---|
102 | "noplain", |
---|
103 | #define OPT_NOACTIVE (1) |
---|
104 | "noactive", |
---|
105 | #define OPT_NODICT (2) |
---|
106 | "nodict", |
---|
107 | #define OPT_FORWARDSEC (3) |
---|
108 | "forwardsec", |
---|
109 | #define OPT_NOANONYMOUS (4) |
---|
110 | "noanonymous", |
---|
111 | #define OPT_PASSCRED (5) |
---|
112 | "passcred", |
---|
113 | NULL |
---|
114 | }; |
---|
115 | |
---|
116 | static const char *ip_subopts[] = { |
---|
117 | #define OPT_IP_LOCAL (0) |
---|
118 | "local", |
---|
119 | #define OPT_IP_REMOTE (1) |
---|
120 | "remote", |
---|
121 | NULL |
---|
122 | }; |
---|
123 | |
---|
124 | char *mech = NULL, |
---|
125 | *iplocal = NULL, |
---|
126 | *ipremote = NULL, |
---|
127 | *searchpath = NULL, |
---|
128 | *service = "rcmd", |
---|
129 | *localdomain = NULL, |
---|
130 | *userdomain = NULL; |
---|
131 | sasl_conn_t *conn = NULL; |
---|
132 | |
---|
133 | static void |
---|
134 | free_conn(void) |
---|
135 | { |
---|
136 | if (conn) |
---|
137 | sasl_dispose(&conn); |
---|
138 | } |
---|
139 | |
---|
140 | static int |
---|
141 | sasl_my_log(void *context __attribute__((unused)), |
---|
142 | int priority, |
---|
143 | const char *message) |
---|
144 | { |
---|
145 | const char *label; |
---|
146 | |
---|
147 | if (! message) |
---|
148 | return SASL_BADPARAM; |
---|
149 | |
---|
150 | switch (priority) { |
---|
151 | case SASL_LOG_ERR: |
---|
152 | label = "Error"; |
---|
153 | break; |
---|
154 | case SASL_LOG_NOTE: |
---|
155 | label = "Info"; |
---|
156 | break; |
---|
157 | default: |
---|
158 | label = "Other"; |
---|
159 | break; |
---|
160 | } |
---|
161 | |
---|
162 | fprintf(stderr, "%s: SASL %s: %s\n", |
---|
163 | progname, label, message); |
---|
164 | |
---|
165 | return SASL_OK; |
---|
166 | } |
---|
167 | |
---|
168 | static int |
---|
169 | getpath(void *context __attribute__((unused)), |
---|
170 | char ** path) |
---|
171 | { |
---|
172 | if (! path) |
---|
173 | return SASL_BADPARAM; |
---|
174 | |
---|
175 | if (searchpath) { |
---|
176 | *path = searchpath; |
---|
177 | } else { |
---|
178 | *path = PLUGINDIR; |
---|
179 | } |
---|
180 | |
---|
181 | return SASL_OK; |
---|
182 | } |
---|
183 | |
---|
184 | static sasl_callback_t callbacks[] = { |
---|
185 | { |
---|
186 | SASL_CB_LOG, &sasl_my_log, NULL |
---|
187 | }, { |
---|
188 | SASL_CB_GETPATH, &getpath, NULL |
---|
189 | }, { |
---|
190 | SASL_CB_LIST_END, NULL, NULL |
---|
191 | } |
---|
192 | }; |
---|
193 | |
---|
194 | static void |
---|
195 | sasldebug(int why, const char *what, const char *errstr) |
---|
196 | { |
---|
197 | fprintf(stderr, "%s: %s: %s", |
---|
198 | progname, |
---|
199 | what, |
---|
200 | sasl_errstring(why, NULL, NULL)); |
---|
201 | if (errstr) |
---|
202 | fprintf(stderr, " (%s)\n", errstr); |
---|
203 | else |
---|
204 | putc('\n', stderr); |
---|
205 | } |
---|
206 | |
---|
207 | static void |
---|
208 | saslfail(int why, const char *what, const char *errstr) |
---|
209 | { |
---|
210 | sasldebug(why, what, errstr); |
---|
211 | exit(EXIT_FAILURE); |
---|
212 | } |
---|
213 | |
---|
214 | static void |
---|
215 | fail(const char *what) |
---|
216 | { |
---|
217 | fprintf(stderr, "%s: %s\n", |
---|
218 | progname, what); |
---|
219 | exit(EXIT_FAILURE); |
---|
220 | } |
---|
221 | |
---|
222 | static void |
---|
223 | osfail() |
---|
224 | { |
---|
225 | perror(progname); |
---|
226 | exit(EXIT_FAILURE); |
---|
227 | } |
---|
228 | |
---|
229 | static void |
---|
230 | samp_send(const char *buffer, |
---|
231 | unsigned length) |
---|
232 | { |
---|
233 | char *buf; |
---|
234 | unsigned len, alloclen; |
---|
235 | int result; |
---|
236 | |
---|
237 | alloclen = ((length / 3) + 1) * 4 + 1; |
---|
238 | buf = malloc(alloclen); |
---|
239 | if (! buf) |
---|
240 | osfail(); |
---|
241 | |
---|
242 | result = sasl_encode64(buffer, length, buf, alloclen, &len); |
---|
243 | if (result != SASL_OK) |
---|
244 | saslfail(result, "Encoding data in base64", NULL); |
---|
245 | printf("S: %s\n", buf); |
---|
246 | free(buf); |
---|
247 | } |
---|
248 | |
---|
249 | static unsigned |
---|
250 | samp_recv() |
---|
251 | { |
---|
252 | unsigned len; |
---|
253 | int result; |
---|
254 | |
---|
255 | if (! fgets(buf, SAMPLE_SEC_BUF_SIZE, stdin)) |
---|
256 | fail("Unable to parse input"); |
---|
257 | |
---|
258 | if (strncmp(buf, "C: ", 3)!=0) |
---|
259 | fail("Line must start with 'C: '"); |
---|
260 | |
---|
261 | result = sasl_decode64(buf + 3, strlen(buf + 3), buf, |
---|
262 | SAMPLE_SEC_BUF_SIZE, &len); |
---|
263 | if (result != SASL_OK) |
---|
264 | saslfail(result, "Decoding data from base64", NULL); |
---|
265 | buf[len] = '\0'; |
---|
266 | printf("got '%s'\n", buf); |
---|
267 | return len; |
---|
268 | } |
---|
269 | |
---|
270 | |
---|
271 | int |
---|
272 | main(int argc, char *argv[]) |
---|
273 | { |
---|
274 | int c = 0; |
---|
275 | int errflag = 0; |
---|
276 | int result; |
---|
277 | sasl_security_properties_t secprops; |
---|
278 | sasl_ssf_t extssf = 0; |
---|
279 | const char *ext_authid = NULL; |
---|
280 | char *options, *value; |
---|
281 | unsigned len, count; |
---|
282 | const char *data; |
---|
283 | int serverlast = 0; |
---|
284 | sasl_ssf_t *ssf; |
---|
285 | |
---|
286 | progname = strrchr(argv[0], '/'); |
---|
287 | if (progname) |
---|
288 | progname++; |
---|
289 | else |
---|
290 | progname = argv[0]; |
---|
291 | |
---|
292 | /* Init defaults... */ |
---|
293 | memset(&secprops, 0L, sizeof(secprops)); |
---|
294 | secprops.maxbufsize = SAMPLE_SEC_BUF_SIZE; |
---|
295 | secprops.max_ssf = UINT_MAX; |
---|
296 | |
---|
297 | verbose = 0; |
---|
298 | while ((c = getopt(argc, argv, "vlhb:e:m:f:i:p:s:d:u:?")) != EOF) |
---|
299 | switch (c) { |
---|
300 | case 'v': |
---|
301 | verbose = 1; |
---|
302 | break; |
---|
303 | case 'b': |
---|
304 | options = optarg; |
---|
305 | while (*options != '\0') |
---|
306 | switch(getsubopt(&options, (const char * const *)bit_subopts, &value)) { |
---|
307 | case OPT_MIN: |
---|
308 | if (! value) |
---|
309 | errflag = 1; |
---|
310 | else |
---|
311 | secprops.min_ssf = atoi(value); |
---|
312 | break; |
---|
313 | case OPT_MAX: |
---|
314 | if (! value) |
---|
315 | errflag = 1; |
---|
316 | else |
---|
317 | secprops.max_ssf = atoi(value); |
---|
318 | break; |
---|
319 | default: |
---|
320 | errflag = 1; |
---|
321 | break; |
---|
322 | } |
---|
323 | break; |
---|
324 | |
---|
325 | case 'e': |
---|
326 | options = optarg; |
---|
327 | while (*options != '\0') |
---|
328 | switch(getsubopt(&options, (const char * const *)ext_subopts, &value)) { |
---|
329 | case OPT_EXT_SSF: |
---|
330 | if (! value) |
---|
331 | errflag = 1; |
---|
332 | else |
---|
333 | extssf = atoi(value); |
---|
334 | break; |
---|
335 | case OPT_MAX: |
---|
336 | if (! value) |
---|
337 | errflag = 1; |
---|
338 | else |
---|
339 | ext_authid = value; |
---|
340 | break; |
---|
341 | default: |
---|
342 | errflag = 1; |
---|
343 | break; |
---|
344 | } |
---|
345 | break; |
---|
346 | |
---|
347 | case 'm': |
---|
348 | mech = optarg; |
---|
349 | break; |
---|
350 | |
---|
351 | case 'f': |
---|
352 | options = optarg; |
---|
353 | while (*options != '\0') { |
---|
354 | switch(getsubopt(&options, (const char * const *)flag_subopts, &value)) { |
---|
355 | case OPT_NOPLAIN: |
---|
356 | secprops.security_flags |= SASL_SEC_NOPLAINTEXT; |
---|
357 | break; |
---|
358 | case OPT_NOACTIVE: |
---|
359 | secprops.security_flags |= SASL_SEC_NOACTIVE; |
---|
360 | break; |
---|
361 | case OPT_NODICT: |
---|
362 | secprops.security_flags |= SASL_SEC_NODICTIONARY; |
---|
363 | break; |
---|
364 | case OPT_FORWARDSEC: |
---|
365 | secprops.security_flags |= SASL_SEC_FORWARD_SECRECY; |
---|
366 | break; |
---|
367 | case OPT_NOANONYMOUS: |
---|
368 | secprops.security_flags |= SASL_SEC_NOANONYMOUS; |
---|
369 | break; |
---|
370 | case OPT_PASSCRED: |
---|
371 | secprops.security_flags |= SASL_SEC_PASS_CREDENTIALS; |
---|
372 | break; |
---|
373 | default: |
---|
374 | errflag = 1; |
---|
375 | break; |
---|
376 | } |
---|
377 | if (value) errflag = 1; |
---|
378 | } |
---|
379 | break; |
---|
380 | |
---|
381 | case 'l': |
---|
382 | serverlast = SASL_SUCCESS_DATA; |
---|
383 | break; |
---|
384 | |
---|
385 | case 'i': |
---|
386 | options = optarg; |
---|
387 | while (*options != '\0') |
---|
388 | switch(getsubopt(&options, (const char * const *)ip_subopts, &value)) { |
---|
389 | case OPT_IP_LOCAL: |
---|
390 | if (! value) |
---|
391 | errflag = 1; |
---|
392 | else |
---|
393 | iplocal = value; |
---|
394 | break; |
---|
395 | case OPT_IP_REMOTE: |
---|
396 | if (! value) |
---|
397 | errflag = 1; |
---|
398 | else |
---|
399 | ipremote = value; |
---|
400 | break; |
---|
401 | default: |
---|
402 | errflag = 1; |
---|
403 | break; |
---|
404 | } |
---|
405 | break; |
---|
406 | |
---|
407 | case 'p': |
---|
408 | searchpath = optarg; |
---|
409 | break; |
---|
410 | |
---|
411 | case 's': |
---|
412 | service = optarg; |
---|
413 | break; |
---|
414 | |
---|
415 | case 'd': |
---|
416 | localdomain = optarg; |
---|
417 | break; |
---|
418 | |
---|
419 | case 'u': |
---|
420 | userdomain = optarg; |
---|
421 | break; |
---|
422 | |
---|
423 | default: |
---|
424 | errflag = 1; |
---|
425 | break; |
---|
426 | } |
---|
427 | |
---|
428 | if (optind != argc) { |
---|
429 | |
---|
430 | errflag = 1; |
---|
431 | } |
---|
432 | |
---|
433 | if (errflag) { |
---|
434 | fprintf(stderr, "%s: Usage: %s [-b min=N,max=N] [-e ssf=N,id=ID] [-m MECH] [-f FLAGS] [-i local=IP,remote=IP] [-p PATH] [-d DOM] [-u DOM] [-s NAME]\n" |
---|
435 | "\t-b ...\t#bits to use for encryption\n" |
---|
436 | "\t\tmin=N\tminumum #bits to use (1 => integrity)\n" |
---|
437 | "\t\tmax=N\tmaximum #bits to use\n" |
---|
438 | "\t-e ...\tassume external encryption\n" |
---|
439 | "\t\tssf=N\texternal mech provides N bits of encryption\n" |
---|
440 | "\t\tid=ID\texternal mech provides authentication id ID\n" |
---|
441 | "\t-m MECH\tforce use of MECH for security\n" |
---|
442 | "\t-f ...\tset security flags\n" |
---|
443 | "\t\tnoplain\t\trequire security vs. passive attacks\n" |
---|
444 | "\t\tnoactive\trequire security vs. active attacks\n" |
---|
445 | "\t\tnodict\t\trequire security vs. passive dictionary attacks\n" |
---|
446 | "\t\tforwardsec\trequire forward secrecy\n" |
---|
447 | "\t\tmaximum\t\trequire all security flags\n" |
---|
448 | "\t\tpasscred\tattempt to receive client credentials\n" |
---|
449 | "\t-i ...\tset IP addresses (required by some mechs)\n" |
---|
450 | "\t\tlocal=IP;PORT\tset local address to IP, port PORT\n" |
---|
451 | "\t\tremote=IP;PORT\tset remote address to IP, port PORT\n" |
---|
452 | "\t-p PATH\tcolon-seperated search path for mechanisms\n" |
---|
453 | "\t-s NAME\tservice name to pass to mechanisms\n" |
---|
454 | "\t-d DOM\tlocal server domain\n" |
---|
455 | "\t-u DOM\tuser domain\n" |
---|
456 | "\t-l\tenable server-send-last\n", |
---|
457 | progname, progname); |
---|
458 | exit(EXIT_FAILURE); |
---|
459 | } |
---|
460 | |
---|
461 | result = sasl_server_init(callbacks, "sample"); |
---|
462 | if (result != SASL_OK) |
---|
463 | saslfail(result, "Initializing libsasl", NULL); |
---|
464 | |
---|
465 | atexit(&sasl_done); |
---|
466 | |
---|
467 | result = sasl_server_new(service, |
---|
468 | localdomain, |
---|
469 | userdomain, |
---|
470 | iplocal, |
---|
471 | ipremote, |
---|
472 | NULL, |
---|
473 | serverlast, |
---|
474 | &conn); |
---|
475 | if (result != SASL_OK) |
---|
476 | saslfail(result, "Allocating sasl connection state", NULL); |
---|
477 | |
---|
478 | atexit(&free_conn); |
---|
479 | |
---|
480 | if(extssf) { |
---|
481 | result = sasl_setprop(conn, |
---|
482 | SASL_SSF_EXTERNAL, |
---|
483 | &extssf); |
---|
484 | |
---|
485 | if (result != SASL_OK) |
---|
486 | saslfail(result, "Setting external SSF", NULL); |
---|
487 | } |
---|
488 | |
---|
489 | if(ext_authid) { |
---|
490 | result = sasl_setprop(conn, |
---|
491 | SASL_AUTH_EXTERNAL, |
---|
492 | &ext_authid); |
---|
493 | |
---|
494 | if (result != SASL_OK) |
---|
495 | saslfail(result, "Setting external authid", NULL); |
---|
496 | } |
---|
497 | |
---|
498 | result = sasl_setprop(conn, |
---|
499 | SASL_SEC_PROPS, |
---|
500 | &secprops); |
---|
501 | |
---|
502 | if (result != SASL_OK) |
---|
503 | saslfail(result, "Setting security properties", NULL); |
---|
504 | |
---|
505 | if (mech) { |
---|
506 | printf("Forcing use of mechanism %s\n", mech); |
---|
507 | data = strdup(mech); |
---|
508 | if (! data) |
---|
509 | osfail(); |
---|
510 | len = strlen(data); |
---|
511 | count = 1; |
---|
512 | } else { |
---|
513 | puts("Generating client mechanism list..."); |
---|
514 | result = sasl_listmech(conn, |
---|
515 | ext_authid, |
---|
516 | NULL, |
---|
517 | " ", |
---|
518 | NULL, |
---|
519 | &data, |
---|
520 | &len, |
---|
521 | &count); |
---|
522 | if (result != SASL_OK) |
---|
523 | saslfail(result, "Generating client mechanism list", NULL); |
---|
524 | } |
---|
525 | |
---|
526 | printf("Sending list of %d mechanism(s)\n", count); |
---|
527 | samp_send(data, len); |
---|
528 | |
---|
529 | if(mech) { |
---|
530 | free((void *)data); |
---|
531 | } |
---|
532 | |
---|
533 | puts("Waiting for client mechanism..."); |
---|
534 | len = samp_recv(); |
---|
535 | if (mech && strcasecmp(mech, buf)) |
---|
536 | fail("Client chose something other than the mandatory mechanism"); |
---|
537 | if (strlen(buf) < len) { |
---|
538 | /* Hmm, there's an initial response here */ |
---|
539 | data = buf + strlen(buf) + 1; |
---|
540 | len = len - strlen(buf) - 1; |
---|
541 | } else { |
---|
542 | data = NULL; |
---|
543 | len = 0; |
---|
544 | } |
---|
545 | result = sasl_server_start(conn, |
---|
546 | buf, |
---|
547 | data, |
---|
548 | len, |
---|
549 | &data, |
---|
550 | &len); |
---|
551 | if (result != SASL_OK && result != SASL_CONTINUE) |
---|
552 | saslfail(result, "Starting SASL negotiation", sasl_errstring(result,NULL,NULL)); |
---|
553 | |
---|
554 | while (result == SASL_CONTINUE) { |
---|
555 | if (data) { |
---|
556 | puts("Sending response..."); |
---|
557 | samp_send(data, len); |
---|
558 | } else |
---|
559 | fail("No data to send--something's wrong"); |
---|
560 | puts("Waiting for client reply..."); |
---|
561 | len = samp_recv(); |
---|
562 | data = NULL; |
---|
563 | result = sasl_server_step(conn, buf, len, |
---|
564 | &data, &len); |
---|
565 | if (result != SASL_OK && result != SASL_CONTINUE) |
---|
566 | saslfail(result, "Performing SASL negotiation", sasl_errstring(result,NULL,NULL)); |
---|
567 | } |
---|
568 | puts("Negotiation complete"); |
---|
569 | |
---|
570 | if(serverlast&&data) { |
---|
571 | printf("might need additional send:\n"); |
---|
572 | samp_send(data,len); |
---|
573 | } |
---|
574 | |
---|
575 | result = sasl_getprop(conn, SASL_USERNAME, (const void **)&data); |
---|
576 | if (result != SASL_OK) |
---|
577 | sasldebug(result, "username", NULL); |
---|
578 | else |
---|
579 | printf("Username: %s\n", data); |
---|
580 | |
---|
581 | result = sasl_getprop(conn, SASL_DEFUSERREALM, (const void **)&data); |
---|
582 | if (result != SASL_OK) |
---|
583 | sasldebug(result, "realm", NULL); |
---|
584 | else |
---|
585 | printf("Realm: %s\n", data); |
---|
586 | |
---|
587 | result = sasl_getprop(conn, SASL_SSF, (const void **)&ssf); |
---|
588 | if (result != SASL_OK) |
---|
589 | sasldebug(result, "ssf", NULL); |
---|
590 | else |
---|
591 | printf("SSF: %d\n", *ssf); |
---|
592 | #define CLIENT_MSG1 "client message 1" |
---|
593 | #define SERVER_MSG1 "srv message 1" |
---|
594 | result=sasl_encode(conn,SERVER_MSG1,sizeof(SERVER_MSG1), |
---|
595 | &data,&len); |
---|
596 | if (result != SASL_OK) |
---|
597 | saslfail(result, "sasl_encode", NULL); |
---|
598 | printf("sending encrypted message '%s'\n",SERVER_MSG1); |
---|
599 | samp_send(data,len); |
---|
600 | printf("Waiting for encrypted message...\n"); |
---|
601 | len=samp_recv(); |
---|
602 | { |
---|
603 | unsigned int recv_len; |
---|
604 | const char *recv_data; |
---|
605 | result=sasl_decode(conn,buf,len,&recv_data,&recv_len); |
---|
606 | if (result != SASL_OK) |
---|
607 | saslfail(result, "sasl_encode", NULL); |
---|
608 | printf("recieved decoded message '%s'\n",recv_data); |
---|
609 | if(strcmp(recv_data,CLIENT_MSG1)!=0) |
---|
610 | saslfail(1,"recive decoded server message",NULL); |
---|
611 | } |
---|
612 | |
---|
613 | return (EXIT_SUCCESS); |
---|
614 | } |
---|