1 /* Generic SASL plugin utility functions
2 * Rob Siemborski
3 */
4 /*
5 * Copyright (c) 1998-2016 Carnegie Mellon University. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. The name "Carnegie Mellon University" must not be used to
20 * endorse or promote products derived from this software without
21 * prior written permission. For permission or any other legal
22 * details, please contact
23 * Carnegie Mellon University
24 * Center for Technology Transfer and Enterprise Creation
25 * 4615 Forbes Avenue
26 * Suite 302
27 * Pittsburgh, PA 15213
28 * (412) 268-7393, fax: (412) 268-7395
29 * innovation@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 #ifndef macintosh
47 #ifdef WIN32
48 # include <winsock2.h>
49 # include <versionhelpers.h>
50 #else
51 # include <sys/socket.h>
52 # include <netinet/in.h>
53 # include <arpa/inet.h>
54 # include <netdb.h>
55 # include <sys/utsname.h>
56 #endif /* WIN32 */
57 #endif /* macintosh */
58 #ifdef HAVE_UNISTD_H
59 #include <unistd.h>
60 #endif
61 #include <fcntl.h>
62 #include <sasl.h>
63 #include <saslutil.h>
64 #include <saslplug.h>
65
66 #include <errno.h>
67 #include <ctype.h>
68 #include <stdio.h>
69
70 #ifdef HAVE_INTTYPES_H
71 #include <inttypes.h>
72 #endif
73
74 #include "plugin_common.h"
75
76 /* translate IPv4 mapped IPv6 address to IPv4 address */
sockaddr_unmapped(struct sockaddr * sa,socklen_t * len)77 static void sockaddr_unmapped(
78 #ifdef IN6_IS_ADDR_V4MAPPED
79 struct sockaddr *sa, socklen_t *len
80 #else
81 struct sockaddr *sa __attribute__((unused)),
82 socklen_t *len __attribute__((unused))
83 #endif
84 )
85 {
86 #ifdef IN6_IS_ADDR_V4MAPPED
87 struct sockaddr_in6 *sin6;
88 struct sockaddr_in *sin4;
89 uint32_t addr;
90 int port;
91
92 if (sa->sa_family != AF_INET6)
93 return;
94 sin6 = (struct sockaddr_in6 *)sa;
95 if (!IN6_IS_ADDR_V4MAPPED((&sin6->sin6_addr)))
96 return;
97 sin4 = (struct sockaddr_in *)sa;
98 #ifdef s6_addr32
99 addr = *(uint32_t *)&sin6->sin6_addr.s6_addr32[3];
100 #else
101 memcpy(&addr, &sin6->sin6_addr.s6_addr[12], 4);
102 #endif
103 port = sin6->sin6_port;
104 memset(sin4, 0, sizeof(struct sockaddr_in));
105 sin4->sin_addr.s_addr = addr;
106 sin4->sin_port = port;
107 sin4->sin_family = AF_INET;
108 #ifdef HAVE_SOCKADDR_SA_LEN
109 sin4->sin_len = sizeof(struct sockaddr_in);
110 #endif
111 *len = sizeof(struct sockaddr_in);
112 #else
113 return;
114 #endif
115 }
116
_plug_ipfromstring(const sasl_utils_t * utils,const char * addr,struct sockaddr * out,socklen_t outlen)117 int _plug_ipfromstring(const sasl_utils_t *utils, const char *addr,
118 struct sockaddr *out, socklen_t outlen)
119 {
120 int i, j;
121 socklen_t len;
122 struct sockaddr_storage ss;
123 struct addrinfo hints, *ai = NULL;
124 char hbuf[NI_MAXHOST];
125
126 if(!utils || !addr || !out) {
127 if(utils) PARAMERROR( utils );
128 return SASL_BADPARAM;
129 }
130
131 /* Parse the address */
132 for (i = 0; addr[i] != '\0' && addr[i] != ';'; i++) {
133 if (i + 1 >= NI_MAXHOST) {
134 if(utils) PARAMERROR( utils );
135 return SASL_BADPARAM;
136 }
137 hbuf[i] = addr[i];
138 }
139 hbuf[i] = '\0';
140
141 if (addr[i] == ';')
142 i++;
143 /* XXX/FIXME: Do we need this check? */
144 for (j = i; addr[j] != '\0'; j++)
145 if (!isdigit((int)(addr[j]))) {
146 PARAMERROR( utils );
147 return SASL_BADPARAM;
148 }
149
150 memset(&hints, 0, sizeof(hints));
151 hints.ai_family = PF_UNSPEC;
152 hints.ai_socktype = SOCK_STREAM;
153 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
154
155 if (getaddrinfo(hbuf, &addr[i], &hints, &ai) != 0) {
156 PARAMERROR( utils );
157 return SASL_BADPARAM;
158 }
159
160 len = (socklen_t) ai->ai_addrlen;
161 memcpy(&ss, ai->ai_addr, len);
162 freeaddrinfo(ai);
163 sockaddr_unmapped((struct sockaddr *)&ss, &len);
164 if (outlen < len) {
165 PARAMERROR( utils );
166 return SASL_BUFOVER;
167 }
168
169 memcpy(out, &ss, len);
170
171 return SASL_OK;
172 }
173
_plug_iovec_to_buf(const sasl_utils_t * utils,const struct iovec * vec,unsigned numiov,buffer_info_t ** output)174 int _plug_iovec_to_buf(const sasl_utils_t *utils, const struct iovec *vec,
175 unsigned numiov, buffer_info_t **output)
176 {
177 unsigned i;
178 int ret;
179 buffer_info_t *out;
180 char *pos;
181
182 if(!utils || !vec || !output) {
183 if(utils) PARAMERROR( utils );
184 return SASL_BADPARAM;
185 }
186
187 if(!(*output)) {
188 *output = utils->malloc(sizeof(buffer_info_t));
189 if(!*output) {
190 MEMERROR(utils);
191 return SASL_NOMEM;
192 }
193 memset(*output,0,sizeof(buffer_info_t));
194 }
195
196 out = *output;
197
198 out->curlen = 0;
199 for(i=0; i<numiov; i++)
200 out->curlen += vec[i].iov_len;
201
202 ret = _plug_buf_alloc(utils, &out->data, &out->reallen, out->curlen);
203
204 if(ret != SASL_OK) {
205 MEMERROR(utils);
206 return SASL_NOMEM;
207 }
208
209 memset(out->data, 0, out->reallen);
210 pos = out->data;
211
212 for(i=0; i<numiov; i++) {
213 memcpy(pos, vec[i].iov_base, vec[i].iov_len);
214 pos += vec[i].iov_len;
215 }
216
217 return SASL_OK;
218 }
219
220 /* Basically a conditional call to realloc(), if we need more */
_plug_buf_alloc(const sasl_utils_t * utils,char ** rwbuf,unsigned * curlen,unsigned newlen)221 int _plug_buf_alloc(const sasl_utils_t *utils, char **rwbuf,
222 unsigned *curlen, unsigned newlen)
223 {
224 if(!utils || !rwbuf || !curlen) {
225 if (utils) PARAMERROR(utils);
226 return SASL_BADPARAM;
227 }
228
229 if(!(*rwbuf)) {
230 *rwbuf = utils->malloc(newlen);
231 if (*rwbuf == NULL) {
232 *curlen = 0;
233 MEMERROR(utils);
234 return SASL_NOMEM;
235 }
236 *curlen = newlen;
237 } else if(*rwbuf && *curlen < newlen) {
238 unsigned needed = 2*(*curlen);
239
240 while(needed < newlen)
241 needed *= 2;
242
243 *rwbuf = utils->realloc(*rwbuf, needed);
244 if (*rwbuf == NULL) {
245 *curlen = 0;
246 MEMERROR(utils);
247 return SASL_NOMEM;
248 }
249 *curlen = needed;
250 }
251
252 return SASL_OK;
253 }
254
255 /* copy a string */
_plug_strdup(const sasl_utils_t * utils,const char * in,char ** out,int * outlen)256 int _plug_strdup(const sasl_utils_t * utils, const char *in,
257 char **out, int *outlen)
258 {
259 size_t len = 0;
260
261 if(!utils || !in || !out) {
262 if(utils) PARAMERROR(utils);
263 return SASL_BADPARAM;
264 }
265
266 len = strlen(in);
267
268 *out = utils->malloc(len + 1);
269 if (!*out) {
270 MEMERROR(utils);
271 return SASL_NOMEM;
272 }
273
274 strcpy((char *) *out, in);
275
276 if (outlen)
277 *outlen = (int) len;
278
279 return SASL_OK;
280 }
281
_plug_free_string(const sasl_utils_t * utils,char ** str)282 void _plug_free_string(const sasl_utils_t *utils, char **str)
283 {
284 size_t len;
285
286 if (!utils || !str || !(*str)) return;
287
288 len = strlen(*str);
289
290 utils->erasebuffer(*str, (unsigned int) len);
291 utils->free(*str);
292
293 *str=NULL;
294 }
295
_plug_free_secret(const sasl_utils_t * utils,sasl_secret_t ** secret)296 void _plug_free_secret(const sasl_utils_t *utils, sasl_secret_t **secret)
297 {
298 if(!utils || !secret || !(*secret)) return;
299
300 utils->erasebuffer((char *)(*secret)->data, (*secret)->len);
301 utils->free(*secret);
302 *secret = NULL;
303 }
304
305 /*
306 * Trys to find the prompt with the lookingfor id in the prompt list
307 * Returns it if found. NULL otherwise
308 */
_plug_find_prompt(sasl_interact_t ** promptlist,unsigned int lookingfor)309 sasl_interact_t *_plug_find_prompt(sasl_interact_t **promptlist,
310 unsigned int lookingfor)
311 {
312 sasl_interact_t *prompt;
313
314 if (promptlist && *promptlist) {
315 for (prompt = *promptlist; prompt->id != SASL_CB_LIST_END; ++prompt) {
316 if (prompt->id==lookingfor)
317 return prompt;
318 }
319 }
320
321 return NULL;
322 }
323
324 /*
325 * Retrieve the simple string given by the callback id.
326 */
_plug_get_simple(const sasl_utils_t * utils,unsigned int id,int required,const char ** result,sasl_interact_t ** prompt_need)327 int _plug_get_simple(const sasl_utils_t *utils, unsigned int id, int required,
328 const char **result, sasl_interact_t **prompt_need)
329 {
330
331 int ret = SASL_FAIL;
332 sasl_getsimple_t *simple_cb;
333 void *simple_context;
334 sasl_interact_t *prompt;
335
336 *result = NULL;
337
338 /* see if we were given the result in the prompt */
339 prompt = _plug_find_prompt(prompt_need, id);
340 if (prompt != NULL) {
341 /* We prompted, and got.*/
342
343 if (required && !prompt->result) {
344 SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_simple");
345 return SASL_BADPARAM;
346 }
347
348 *result = prompt->result;
349 return SASL_OK;
350 }
351
352 /* Try to get the callback... */
353 ret = utils->getcallback(utils->conn, id, (sasl_callback_ft *)&simple_cb, &simple_context);
354
355 if (ret == SASL_FAIL && !required)
356 return SASL_OK;
357
358 if (ret == SASL_OK && simple_cb) {
359 ret = simple_cb(simple_context, id, result, NULL);
360 if (ret != SASL_OK)
361 return ret;
362
363 if (required && !*result) {
364 PARAMERROR(utils);
365 return SASL_BADPARAM;
366 }
367 }
368
369 return ret;
370 }
371
372 /*
373 * Retrieve the user password.
374 */
_plug_get_password(const sasl_utils_t * utils,sasl_secret_t ** password,unsigned int * iscopy,sasl_interact_t ** prompt_need)375 int _plug_get_password(const sasl_utils_t *utils, sasl_secret_t **password,
376 unsigned int *iscopy, sasl_interact_t **prompt_need)
377 {
378 int ret = SASL_FAIL;
379 sasl_getsecret_t *pass_cb;
380 void *pass_context;
381 sasl_interact_t *prompt;
382
383 *password = NULL;
384 *iscopy = 0;
385
386 /* see if we were given the password in the prompt */
387 prompt = _plug_find_prompt(prompt_need, SASL_CB_PASS);
388 if (prompt != NULL) {
389 /* We prompted, and got.*/
390
391 if (!prompt->result) {
392 SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_password");
393 return SASL_BADPARAM;
394 }
395
396 /* copy what we got into a secret_t */
397 *password = (sasl_secret_t *) utils->malloc(sizeof(sasl_secret_t) +
398 prompt->len + 1);
399 if (!*password) {
400 MEMERROR(utils);
401 return SASL_NOMEM;
402 }
403
404 (*password)->len=prompt->len;
405 memcpy((*password)->data, prompt->result, prompt->len);
406 (*password)->data[(*password)->len]=0;
407
408 *iscopy = 1;
409
410 return SASL_OK;
411 }
412
413 /* Try to get the callback... */
414 ret = utils->getcallback(utils->conn, SASL_CB_PASS,
415 (sasl_callback_ft *)&pass_cb, &pass_context);
416
417 if (ret == SASL_OK && pass_cb) {
418 ret = pass_cb(utils->conn, pass_context, SASL_CB_PASS, password);
419 if (ret != SASL_OK)
420 return ret;
421
422 if (!*password) {
423 PARAMERROR(utils);
424 return SASL_BADPARAM;
425 }
426 }
427
428 return ret;
429 }
430
431 /*
432 * Retrieve the string given by the challenge prompt id.
433 */
_plug_challenge_prompt(const sasl_utils_t * utils,unsigned int id,const char * challenge,const char * promptstr,const char ** result,sasl_interact_t ** prompt_need)434 int _plug_challenge_prompt(const sasl_utils_t *utils, unsigned int id,
435 const char *challenge, const char *promptstr,
436 const char **result, sasl_interact_t **prompt_need)
437 {
438 int ret = SASL_FAIL;
439 sasl_chalprompt_t *chalprompt_cb;
440 void *chalprompt_context;
441 sasl_interact_t *prompt;
442
443 *result = NULL;
444
445 /* see if we were given the password in the prompt */
446 prompt = _plug_find_prompt(prompt_need, id);
447 if (prompt != NULL) {
448 /* We prompted, and got.*/
449
450 if (!prompt->result) {
451 SETERROR(utils, "Unexpectedly missing a prompt result in _plug_challenge_prompt");
452 return SASL_BADPARAM;
453 }
454
455 *result = prompt->result;
456 return SASL_OK;
457 }
458
459 /* Try to get the callback... */
460 ret = utils->getcallback(utils->conn, id,
461 (sasl_callback_ft *)&chalprompt_cb, &chalprompt_context);
462
463 if (ret == SASL_OK && chalprompt_cb) {
464 ret = chalprompt_cb(chalprompt_context, id,
465 challenge, promptstr, NULL, result, NULL);
466 if (ret != SASL_OK)
467 return ret;
468
469 if (!*result) {
470 PARAMERROR(utils);
471 return SASL_BADPARAM;
472 }
473 }
474
475 return ret;
476 }
477
478 /*
479 * Retrieve the client realm.
480 */
_plug_get_realm(const sasl_utils_t * utils,const char ** availrealms,const char ** realm,sasl_interact_t ** prompt_need)481 int _plug_get_realm(const sasl_utils_t *utils, const char **availrealms,
482 const char **realm, sasl_interact_t **prompt_need)
483 {
484 int ret = SASL_FAIL;
485 sasl_getrealm_t *realm_cb;
486 void *realm_context;
487 sasl_interact_t *prompt;
488
489 *realm = NULL;
490
491 /* see if we were given the result in the prompt */
492 prompt = _plug_find_prompt(prompt_need, SASL_CB_GETREALM);
493 if (prompt != NULL) {
494 /* We prompted, and got.*/
495
496 if (!prompt->result) {
497 SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_realm");
498 return SASL_BADPARAM;
499 }
500
501 *realm = prompt->result;
502 return SASL_OK;
503 }
504
505 /* Try to get the callback... */
506 ret = utils->getcallback(utils->conn, SASL_CB_GETREALM,
507 (sasl_callback_ft *)&realm_cb, &realm_context);
508
509 if (ret == SASL_OK && realm_cb) {
510 ret = realm_cb(realm_context, SASL_CB_GETREALM, availrealms, realm);
511 if (ret != SASL_OK)
512 return ret;
513
514 if (!*realm) {
515 PARAMERROR(utils);
516 return SASL_BADPARAM;
517 }
518 }
519
520 return ret;
521 }
522
523 /*
524 * Make the requested prompts. (prompt==NULL means we don't want it)
525 */
_plug_make_prompts(const sasl_utils_t * utils,sasl_interact_t ** prompts_res,const char * user_prompt,const char * user_def,const char * auth_prompt,const char * auth_def,const char * pass_prompt,const char * pass_def,const char * echo_chal,const char * echo_prompt,const char * echo_def,const char * realm_chal,const char * realm_prompt,const char * realm_def)526 int _plug_make_prompts(const sasl_utils_t *utils,
527 sasl_interact_t **prompts_res,
528 const char *user_prompt, const char *user_def,
529 const char *auth_prompt, const char *auth_def,
530 const char *pass_prompt, const char *pass_def,
531 const char *echo_chal,
532 const char *echo_prompt, const char *echo_def,
533 const char *realm_chal,
534 const char *realm_prompt, const char *realm_def)
535 {
536 int num = 1;
537 int alloc_size;
538 sasl_interact_t *prompts;
539
540 if (user_prompt) num++;
541 if (auth_prompt) num++;
542 if (pass_prompt) num++;
543 if (echo_prompt) num++;
544 if (realm_prompt) num++;
545
546 if (num == 1) {
547 SETERROR( utils, "make_prompts() called with no actual prompts" );
548 return SASL_FAIL;
549 }
550
551 alloc_size = sizeof(sasl_interact_t)*num;
552 prompts = utils->malloc(alloc_size);
553 if (!prompts) {
554 MEMERROR( utils );
555 return SASL_NOMEM;
556 }
557 memset(prompts, 0, alloc_size);
558
559 *prompts_res = prompts;
560
561 if (user_prompt) {
562 (prompts)->id = SASL_CB_USER;
563 (prompts)->challenge = "Authorization Name";
564 (prompts)->prompt = user_prompt;
565 (prompts)->defresult = user_def;
566
567 prompts++;
568 }
569
570 if (auth_prompt) {
571 (prompts)->id = SASL_CB_AUTHNAME;
572 (prompts)->challenge = "Authentication Name";
573 (prompts)->prompt = auth_prompt;
574 (prompts)->defresult = auth_def;
575
576 prompts++;
577 }
578
579 if (pass_prompt) {
580 (prompts)->id = SASL_CB_PASS;
581 (prompts)->challenge = "Password";
582 (prompts)->prompt = pass_prompt;
583 (prompts)->defresult = pass_def;
584
585 prompts++;
586 }
587
588 if (echo_prompt) {
589 (prompts)->id = SASL_CB_ECHOPROMPT;
590 (prompts)->challenge = echo_chal;
591 (prompts)->prompt = echo_prompt;
592 (prompts)->defresult = echo_def;
593
594 prompts++;
595 }
596
597 if (realm_prompt) {
598 (prompts)->id = SASL_CB_GETREALM;
599 (prompts)->challenge = realm_chal;
600 (prompts)->prompt = realm_prompt;
601 (prompts)->defresult = realm_def;
602
603 prompts++;
604 }
605
606 /* add the ending one */
607 (prompts)->id = SASL_CB_LIST_END;
608 (prompts)->challenge = NULL;
609 (prompts)->prompt = NULL;
610 (prompts)->defresult = NULL;
611
612 return SASL_OK;
613 }
614
_plug_decode_init(decode_context_t * text,const sasl_utils_t * utils,unsigned int in_maxbuf)615 void _plug_decode_init(decode_context_t *text,
616 const sasl_utils_t *utils, unsigned int in_maxbuf)
617 {
618 memset(text, 0, sizeof(decode_context_t));
619
620 text->utils = utils;
621 text->needsize = 4;
622 text->in_maxbuf = in_maxbuf;
623 }
624
625 /*
626 * Decode as much of the input as possible (possibly none),
627 * using decode_pkt() to decode individual packets.
628 */
_plug_decode(decode_context_t * text,const char * input,unsigned inputlen,char ** output,unsigned * outputsize,unsigned * outputlen,int (* decode_pkt)(void * rock,const char * input,unsigned inputlen,char ** output,unsigned * outputlen),void * rock)629 int _plug_decode(decode_context_t *text,
630 const char *input, unsigned inputlen,
631 char **output, /* output buffer */
632 unsigned *outputsize, /* current size of output buffer */
633 unsigned *outputlen, /* length of data in output buffer */
634 int (*decode_pkt)(void *rock,
635 const char *input, unsigned inputlen,
636 char **output, unsigned *outputlen),
637 void *rock)
638 {
639 unsigned int tocopy;
640 unsigned diff;
641 char *tmp;
642 unsigned tmplen;
643 int ret;
644
645 *outputlen = 0;
646
647 while (inputlen) { /* more input */
648 if (text->needsize) { /* need to get the rest of the 4-byte size */
649
650 /* copy as many bytes (up to 4) as we have into size buffer */
651 tocopy = (inputlen > text->needsize) ? text->needsize : inputlen;
652 memcpy(text->sizebuf + 4 - text->needsize, input, tocopy);
653 text->needsize -= tocopy;
654
655 input += tocopy;
656 inputlen -= tocopy;
657
658 if (!text->needsize) { /* we have the entire 4-byte size */
659 memcpy(&(text->size), text->sizebuf, 4);
660 text->size = ntohl(text->size);
661 text->cursize = 0;
662 } else {
663 /* We do NOT have the entire 4-byte size...
664 * wait for more data */
665 return SASL_OK;
666 }
667 }
668
669 if (!text->size) /* should never happen */
670 return SASL_FAIL;
671
672 if (text->size > text->in_maxbuf) {
673 text->utils->log(NULL, SASL_LOG_ERR,
674 "encoded packet size too big (%d > %d)",
675 text->size, text->in_maxbuf);
676 return SASL_FAIL;
677 }
678
679 if (!text->buffer) {
680 text->buffer = text->utils->malloc(text->in_maxbuf);
681 if (text->buffer == NULL) return SASL_NOMEM;
682 }
683
684 diff = text->size - text->cursize; /* bytes needed for full packet */
685
686 if (inputlen < diff) { /* not a complete packet, need more input */
687 memcpy(text->buffer + text->cursize, input, inputlen);
688 text->cursize += inputlen;
689 return SASL_OK;
690 }
691
692 /* copy the rest of the packet */
693 memcpy(text->buffer + text->cursize, input, diff);
694 input += diff;
695 inputlen -= diff;
696
697 /* decode the packet (no need to free tmp) */
698 ret = decode_pkt(rock, text->buffer, text->size, &tmp, &tmplen);
699 if (ret != SASL_OK) return ret;
700
701 /* append the decoded packet to the output */
702 ret = _plug_buf_alloc(text->utils, output, outputsize,
703 *outputlen + tmplen + 1); /* +1 for NUL */
704 if (ret != SASL_OK) return ret;
705
706 memcpy(*output + *outputlen, tmp, tmplen);
707 *outputlen += tmplen;
708
709 /* protect stupid clients */
710 *(*output + *outputlen) = '\0';
711
712 /* reset for the next packet */
713 text->needsize = 4;
714 }
715
716 return SASL_OK;
717 }
718
_plug_decode_free(decode_context_t * text)719 void _plug_decode_free(decode_context_t *text)
720 {
721 if (text->buffer) text->utils->free(text->buffer);
722 }
723
724 /* returns the realm we should pretend to be in */
_plug_parseuser(const sasl_utils_t * utils,char ** user,char ** realm,const char * user_realm,const char * serverFQDN,const char * input)725 int _plug_parseuser(const sasl_utils_t *utils,
726 char **user, char **realm, const char *user_realm,
727 const char *serverFQDN, const char *input)
728 {
729 int ret;
730 char *r;
731
732 if(!user || !serverFQDN) {
733 PARAMERROR( utils );
734 return SASL_BADPARAM;
735 }
736
737 r = strchr(input, '@');
738 if (!r) {
739 /* hmmm, the user didn't specify a realm */
740 if(user_realm && user_realm[0]) {
741 ret = _plug_strdup(utils, user_realm, realm, NULL);
742 } else {
743 /* Default to serverFQDN */
744 ret = _plug_strdup(utils, serverFQDN, realm, NULL);
745 }
746
747 if (ret == SASL_OK) {
748 ret = _plug_strdup(utils, input, user, NULL);
749 }
750 } else {
751 r++;
752 ret = _plug_strdup(utils, r, realm, NULL);
753 *--r = '\0';
754 *user = utils->malloc(r - input + 1);
755 if (*user) {
756 strncpy(*user, input, r - input +1);
757 } else {
758 MEMERROR( utils );
759 ret = SASL_NOMEM;
760 }
761 *r = '@';
762 }
763
764 return ret;
765 }
766
_plug_make_fulluser(const sasl_utils_t * utils,char ** fulluser,const char * useronly,const char * realm)767 int _plug_make_fulluser(const sasl_utils_t *utils,
768 char **fulluser,
769 const char * useronly,
770 const char *realm)
771 {
772 if(!fulluser || !useronly || !realm) {
773 PARAMERROR( utils );
774 return (SASL_BADPARAM);
775 }
776
777 *fulluser = utils->malloc (strlen(useronly) + strlen(realm) + 2);
778 if (*fulluser == NULL) {
779 MEMERROR( utils );
780 return (SASL_NOMEM);
781 }
782
783 strcpy (*fulluser, useronly);
784 strcat (*fulluser, "@");
785 strcat (*fulluser, realm);
786
787 return (SASL_OK);
788 }
789
_plug_get_error_message(const sasl_utils_t * utils,DWORD error)790 char * _plug_get_error_message (const sasl_utils_t *utils,
791 #ifdef WIN32
792 DWORD error
793 #else
794 int error
795 #endif
796 )
797 {
798 char * return_value;
799 #ifdef WIN32
800 LPVOID lpMsgBuf;
801
802 FormatMessage(
803 FORMAT_MESSAGE_ALLOCATE_BUFFER |
804 FORMAT_MESSAGE_FROM_SYSTEM |
805 FORMAT_MESSAGE_IGNORE_INSERTS,
806 NULL,
807 error,
808 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
809 (LPTSTR) &lpMsgBuf,
810 0,
811 NULL
812 );
813
814 if (_plug_strdup (utils, lpMsgBuf, &return_value, NULL) != SASL_OK) {
815 return_value = NULL;
816 }
817
818 LocalFree( lpMsgBuf );
819 #else /* !WIN32 */
820 if (_plug_strdup (utils, strerror(error), &return_value, NULL) != SASL_OK) {
821 return_value = NULL;
822 }
823 #endif /* WIN32 */
824 return (return_value);
825 }
826
_plug_snprintf_os_info(char * osbuf,int osbuf_len)827 void _plug_snprintf_os_info (char * osbuf, int osbuf_len)
828 {
829 #ifdef WIN32
830 char *sysname;
831 sysname = "Unknown Windows";
832
833 /* Let's suppose it's still compilable with win2k sdk. So define everythig missing */
834 #ifndef _WIN32_WINNT_WINXP
835 # define _WIN32_WINNT_WINXP 0x0501
836 #endif
837 #ifndef _WIN32_WINNT_WS03
838 # define _WIN32_WINNT_WS03 0x0502
839 #endif
840 #ifndef _WIN32_WINNT_WIN6
841 # define _WIN32_WINNT_WIN6 0x0600
842 #endif
843 #ifndef _WIN32_WINNT_VISTA
844 # define _WIN32_WINNT_VISTA 0x0600
845 #endif
846 #ifndef _WIN32_WINNT_WS08
847 # define _WIN32_WINNT_WS08 0x0600
848 #endif
849 #ifndef _WIN32_WINNT_LONGHORN
850 # define _WIN32_WINNT_LONGHORN 0x0600
851 #endif
852 #ifndef _WIN32_WINNT_WIN7
853 # define _WIN32_WINNT_WIN7 0x0601
854 #endif
855 #ifndef _WIN32_WINNT_WIN8
856 # define _WIN32_WINNT_WIN8 0x0602
857 #endif
858 #ifndef _WIN32_WINNT_WINBLUE
859 # define _WIN32_WINNT_WINBLUE 0x0603
860 #endif
861 #ifndef _WIN32_WINNT_WIN10
862 # define _WIN32_WINNT_WIN10 0x0A00
863 #endif
864
865 /* and use IsWindowsVersionOrGreater instead of convenient wrappers by the same reason */
866 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0)) {
867 sysname = "Windows 10 or greater";
868 } else
869 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0)) {
870 sysname = "Windows 8.1";
871 } else
872 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0)) {
873 sysname = "Windows 8";
874 } else
875 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1)) {
876 sysname = "Windows 7 SP1";
877 } else
878 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0)) {
879 sysname = "Windows 7";
880 } else
881 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2)) {
882 sysname = "Windows Vista SP2";
883 } else
884 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1)) {
885 sysname = "Windows Vista SP1";
886 } else
887 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0)) {
888 sysname = "Windows Vista";
889 } else
890 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3)) {
891 sysname = "Windows XP SP3";
892 } else
893 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2)) {
894 sysname = "Windows XP SP2";
895 } else
896 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1)) {
897 sysname = "Windows XP SP1";
898 } else
899 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0)) {
900 sysname = "Windows XP";
901 }
902
903 snprintf(osbuf, osbuf_len, "%s", sysname);
904
905 #else /* !WIN32 */
906 struct utsname os;
907
908 uname(&os);
909 snprintf(osbuf, osbuf_len, "%s %s", os.sysname, os.release);
910 #endif /* WIN32 */
911 }
912
913 #if defined(WIN32)
plug_sleep(unsigned int seconds)914 unsigned int plug_sleep (unsigned int seconds)
915 {
916 long dwSec = seconds*1000;
917 Sleep (dwSec);
918 return 0;
919 }
920 #endif
921