File indexing completed on 2024-05-12 05:22:31
0001 /* Generic SASL plugin utility functions 0002 * Rob Siemborski 0003 */ 0004 /* 0005 * Copyright (c) 1998-2016 Carnegie Mellon University. All rights reserved. 0006 * 0007 * Redistribution and use in source and binary forms, with or without 0008 * modification, are permitted provided that the following conditions 0009 * are met: 0010 * 0011 * 1. Redistributions of source code must retain the above copyright 0012 * notice, this list of conditions and the following disclaimer. 0013 * 0014 * 2. Redistributions in binary form must reproduce the above copyright 0015 * notice, this list of conditions and the following disclaimer in 0016 * the documentation and/or other materials provided with the 0017 * distribution. 0018 * 0019 * 3. The name "Carnegie Mellon University" must not be used to 0020 * endorse or promote products derived from this software without 0021 * prior written permission. For permission or any other legal 0022 * details, please contact 0023 * Carnegie Mellon University 0024 * Center for Technology Transfer and Enterprise Creation 0025 * 4615 Forbes Avenue 0026 * Suite 302 0027 * Pittsburgh, PA 15213 0028 * (412) 268-7393, fax: (412) 268-7395 0029 * innovation@andrew.cmu.edu 0030 * 0031 * 4. Redistributions of any form whatsoever must retain the following 0032 * acknowledgment: 0033 * "This product includes software developed by Computing Services 0034 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 0035 * 0036 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 0037 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 0038 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 0039 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 0040 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 0041 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 0042 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 0043 */ 0044 0045 #include <config.h> 0046 #ifdef WIN32 0047 #include <versionhelpers.h> 0048 #include <winsock2.h> 0049 #else 0050 #ifndef macintosh 0051 #include <arpa/inet.h> 0052 #include <netdb.h> 0053 #endif /* macintosh */ 0054 #include <netinet/in.h> 0055 #include <sys/socket.h> 0056 #include <sys/utsname.h> 0057 #endif /* WIN32 */ 0058 #ifdef HAVE_UNISTD_H 0059 #include <unistd.h> 0060 #endif 0061 #include <fcntl.h> 0062 #include <sasl/sasl.h> 0063 #include <sasl/saslplug.h> 0064 #include <sasl/saslutil.h> 0065 0066 #include <ctype.h> 0067 #include <errno.h> 0068 #include <stdio.h> 0069 0070 #ifdef HAVE_INTTYPES_H 0071 #include <inttypes.h> 0072 #endif 0073 0074 #include "plugin_common.h" 0075 0076 /* translate IPv4 mapped IPv6 address to IPv4 address */ 0077 static void sockaddr_unmapped( 0078 #ifdef IN6_IS_ADDR_V4MAPPED 0079 struct sockaddr *sa, 0080 socklen_t *len 0081 #else 0082 struct sockaddr *sa __attribute__((unused)), 0083 socklen_t *len __attribute__((unused)) 0084 #endif 0085 ) 0086 { 0087 #ifdef IN6_IS_ADDR_V4MAPPED 0088 struct sockaddr_in6 *sin6; 0089 struct sockaddr_in *sin4; 0090 uint32_t addr; 0091 int port; 0092 0093 if (sa->sa_family != AF_INET6) 0094 return; 0095 sin6 = (struct sockaddr_in6 *)sa; 0096 if (!IN6_IS_ADDR_V4MAPPED((&sin6->sin6_addr))) 0097 return; 0098 sin4 = (struct sockaddr_in *)sa; 0099 #ifdef s6_addr32 0100 addr = *(uint32_t *)&sin6->sin6_addr.s6_addr32[3]; 0101 #else 0102 memcpy(&addr, &sin6->sin6_addr.s6_addr[12], 4); 0103 #endif 0104 port = sin6->sin6_port; 0105 memset(sin4, 0, sizeof(struct sockaddr_in)); 0106 sin4->sin_addr.s_addr = addr; 0107 sin4->sin_port = port; 0108 sin4->sin_family = AF_INET; 0109 #ifdef HAVE_SOCKADDR_SA_LEN 0110 sin4->sin_len = sizeof(struct sockaddr_in); 0111 #endif 0112 *len = sizeof(struct sockaddr_in); 0113 #else 0114 return; 0115 #endif 0116 } 0117 0118 int _plug_ipfromstring(const sasl_utils_t *utils, const char *addr, struct sockaddr *out, socklen_t outlen) 0119 { 0120 int i, j; 0121 socklen_t len; 0122 struct sockaddr_storage ss; 0123 struct addrinfo hints, *ai = NULL; 0124 char hbuf[NI_MAXHOST]; 0125 0126 if (!utils || !addr || !out) { 0127 if (utils) 0128 PARAMERROR(utils); 0129 return SASL_BADPARAM; 0130 } 0131 0132 /* Parse the address */ 0133 for (i = 0; addr[i] != '\0' && addr[i] != ';'; i++) { 0134 if (i + 1 >= NI_MAXHOST) { 0135 if (utils) 0136 PARAMERROR(utils); 0137 return SASL_BADPARAM; 0138 } 0139 hbuf[i] = addr[i]; 0140 } 0141 hbuf[i] = '\0'; 0142 0143 if (addr[i] == ';') 0144 i++; 0145 /* XXX/FIXME: Do we need this check? */ 0146 for (j = i; addr[j] != '\0'; j++) 0147 if (!isdigit((int)(addr[j]))) { 0148 PARAMERROR(utils); 0149 return SASL_BADPARAM; 0150 } 0151 0152 memset(&hints, 0, sizeof(hints)); 0153 hints.ai_family = PF_UNSPEC; 0154 hints.ai_socktype = SOCK_STREAM; 0155 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 0156 0157 if (getaddrinfo(hbuf, &addr[i], &hints, &ai) != 0) { 0158 PARAMERROR(utils); 0159 return SASL_BADPARAM; 0160 } 0161 0162 len = (socklen_t)ai->ai_addrlen; 0163 memcpy(&ss, ai->ai_addr, len); 0164 freeaddrinfo(ai); 0165 sockaddr_unmapped((struct sockaddr *)&ss, &len); 0166 if (outlen < len) { 0167 PARAMERROR(utils); 0168 return SASL_BUFOVER; 0169 } 0170 0171 memcpy(out, &ss, len); 0172 0173 return SASL_OK; 0174 } 0175 0176 int _plug_iovec_to_buf(const sasl_utils_t *utils, const struct iovec *vec, unsigned numiov, buffer_info_t **output) 0177 { 0178 unsigned i; 0179 int ret; 0180 buffer_info_t *out; 0181 char *pos; 0182 0183 if (!utils || !vec || !output) { 0184 if (utils) 0185 PARAMERROR(utils); 0186 return SASL_BADPARAM; 0187 } 0188 0189 if (!(*output)) { 0190 *output = utils->malloc(sizeof(buffer_info_t)); 0191 if (!*output) { 0192 MEMERROR(utils); 0193 return SASL_NOMEM; 0194 } 0195 memset(*output, 0, sizeof(buffer_info_t)); 0196 } 0197 0198 out = *output; 0199 0200 out->curlen = 0; 0201 for (i = 0; i < numiov; i++) 0202 out->curlen += vec[i].iov_len; 0203 0204 ret = _plug_buf_alloc(utils, &out->data, &out->reallen, out->curlen); 0205 0206 if (ret != SASL_OK) { 0207 MEMERROR(utils); 0208 return SASL_NOMEM; 0209 } 0210 0211 memset(out->data, 0, out->reallen); 0212 pos = out->data; 0213 0214 for (i = 0; i < numiov; i++) { 0215 memcpy(pos, vec[i].iov_base, vec[i].iov_len); 0216 pos += vec[i].iov_len; 0217 } 0218 0219 return SASL_OK; 0220 } 0221 0222 /* Basically a conditional call to realloc(), if we need more */ 0223 int _plug_buf_alloc(const sasl_utils_t *utils, char **rwbuf, unsigned *curlen, unsigned newlen) 0224 { 0225 if (!utils || !rwbuf || !curlen) { 0226 if (utils) 0227 PARAMERROR(utils); 0228 return SASL_BADPARAM; 0229 } 0230 0231 if (!(*rwbuf)) { 0232 *rwbuf = utils->malloc(newlen); 0233 if (*rwbuf == NULL) { 0234 *curlen = 0; 0235 MEMERROR(utils); 0236 return SASL_NOMEM; 0237 } 0238 *curlen = newlen; 0239 } else if (*rwbuf && *curlen < newlen) { 0240 unsigned needed = 2 * (*curlen); 0241 0242 while (needed < newlen) 0243 needed *= 2; 0244 0245 *rwbuf = utils->realloc(*rwbuf, needed); 0246 if (*rwbuf == NULL) { 0247 *curlen = 0; 0248 MEMERROR(utils); 0249 return SASL_NOMEM; 0250 } 0251 *curlen = needed; 0252 } 0253 0254 return SASL_OK; 0255 } 0256 0257 /* copy a string */ 0258 int _plug_strdup(const sasl_utils_t *utils, const char *in, char **out, int *outlen) 0259 { 0260 size_t len = 0; 0261 0262 if (!utils || !in || !out) { 0263 if (utils) 0264 PARAMERROR(utils); 0265 return SASL_BADPARAM; 0266 } 0267 0268 len = strlen(in); 0269 0270 *out = utils->malloc(len + 1); 0271 if (!*out) { 0272 MEMERROR(utils); 0273 return SASL_NOMEM; 0274 } 0275 0276 strcpy((char *)*out, in); 0277 0278 if (outlen) 0279 *outlen = (int)len; 0280 0281 return SASL_OK; 0282 } 0283 0284 void _plug_free_string(const sasl_utils_t *utils, char **str) 0285 { 0286 size_t len; 0287 0288 if (!utils || !str || !(*str)) 0289 return; 0290 0291 len = strlen(*str); 0292 0293 utils->erasebuffer(*str, (unsigned int)len); 0294 utils->free(*str); 0295 0296 *str = NULL; 0297 } 0298 0299 void _plug_free_secret(const sasl_utils_t *utils, sasl_secret_t **secret) 0300 { 0301 if (!utils || !secret || !(*secret)) 0302 return; 0303 0304 utils->erasebuffer((char *)(*secret)->data, (*secret)->len); 0305 utils->free(*secret); 0306 *secret = NULL; 0307 } 0308 0309 /* 0310 * Trys to find the prompt with the lookingfor id in the prompt list 0311 * Returns it if found. NULL otherwise 0312 */ 0313 sasl_interact_t *_plug_find_prompt(sasl_interact_t **promptlist, unsigned int lookingfor) 0314 { 0315 sasl_interact_t *prompt; 0316 0317 if (promptlist && *promptlist) { 0318 for (prompt = *promptlist; prompt->id != SASL_CB_LIST_END; ++prompt) { 0319 if (prompt->id == lookingfor) 0320 return prompt; 0321 } 0322 } 0323 0324 return NULL; 0325 } 0326 0327 /* 0328 * Retrieve the simple string given by the callback id. 0329 */ 0330 int _plug_get_simple(const sasl_utils_t *utils, unsigned int id, int required, const char **result, sasl_interact_t **prompt_need) 0331 { 0332 int ret = SASL_FAIL; 0333 sasl_getsimple_t *simple_cb; 0334 void *simple_context; 0335 sasl_interact_t *prompt; 0336 0337 *result = NULL; 0338 0339 /* see if we were given the result in the prompt */ 0340 prompt = _plug_find_prompt(prompt_need, id); 0341 if (prompt != NULL) { 0342 /* We prompted, and got.*/ 0343 0344 if (required && !prompt->result) { 0345 SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_simple"); 0346 return SASL_BADPARAM; 0347 } 0348 0349 *result = prompt->result; 0350 return SASL_OK; 0351 } 0352 0353 /* Try to get the callback... */ 0354 ret = utils->getcallback(utils->conn, id, (sasl_callback_ft *)&simple_cb, &simple_context); 0355 0356 if (ret == SASL_FAIL && !required) 0357 return SASL_OK; 0358 0359 if (ret == SASL_OK && simple_cb) { 0360 ret = simple_cb(simple_context, id, result, NULL); 0361 if (ret != SASL_OK) 0362 return ret; 0363 0364 if (required && !*result) { 0365 PARAMERROR(utils); 0366 return SASL_BADPARAM; 0367 } 0368 } 0369 0370 return ret; 0371 } 0372 0373 /* 0374 * Retrieve the user password. 0375 */ 0376 int _plug_get_password(const sasl_utils_t *utils, sasl_secret_t **password, unsigned int *iscopy, sasl_interact_t **prompt_need) 0377 { 0378 int ret = SASL_FAIL; 0379 sasl_getsecret_t *pass_cb; 0380 void *pass_context; 0381 sasl_interact_t *prompt; 0382 0383 *password = NULL; 0384 *iscopy = 0; 0385 0386 /* see if we were given the password in the prompt */ 0387 prompt = _plug_find_prompt(prompt_need, SASL_CB_PASS); 0388 if (prompt != NULL) { 0389 /* We prompted, and got.*/ 0390 0391 if (!prompt->result) { 0392 SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_password"); 0393 return SASL_BADPARAM; 0394 } 0395 0396 /* copy what we got into a secret_t */ 0397 *password = (sasl_secret_t *)utils->malloc(sizeof(sasl_secret_t) + prompt->len + 1); 0398 if (!*password) { 0399 MEMERROR(utils); 0400 return SASL_NOMEM; 0401 } 0402 0403 (*password)->len = prompt->len; 0404 memcpy((*password)->data, prompt->result, prompt->len); 0405 (*password)->data[(*password)->len] = 0; 0406 0407 *iscopy = 1; 0408 0409 return SASL_OK; 0410 } 0411 0412 /* Try to get the callback... */ 0413 ret = utils->getcallback(utils->conn, SASL_CB_PASS, (sasl_callback_ft *)&pass_cb, &pass_context); 0414 0415 if (ret == SASL_OK && pass_cb) { 0416 ret = pass_cb(utils->conn, pass_context, SASL_CB_PASS, password); 0417 if (ret != SASL_OK) 0418 return ret; 0419 0420 if (!*password) { 0421 PARAMERROR(utils); 0422 return SASL_BADPARAM; 0423 } 0424 } 0425 0426 return ret; 0427 } 0428 0429 /* 0430 * Retrieve the string given by the challenge prompt id. 0431 */ 0432 int _plug_challenge_prompt(const sasl_utils_t *utils, 0433 unsigned int id, 0434 const char *challenge, 0435 const char *promptstr, 0436 const char **result, 0437 sasl_interact_t **prompt_need) 0438 { 0439 int ret = SASL_FAIL; 0440 sasl_chalprompt_t *chalprompt_cb; 0441 void *chalprompt_context; 0442 sasl_interact_t *prompt; 0443 0444 *result = NULL; 0445 0446 /* see if we were given the password in the prompt */ 0447 prompt = _plug_find_prompt(prompt_need, id); 0448 if (prompt != NULL) { 0449 /* We prompted, and got.*/ 0450 0451 if (!prompt->result) { 0452 SETERROR(utils, "Unexpectedly missing a prompt result in _plug_challenge_prompt"); 0453 return SASL_BADPARAM; 0454 } 0455 0456 *result = prompt->result; 0457 return SASL_OK; 0458 } 0459 0460 /* Try to get the callback... */ 0461 ret = utils->getcallback(utils->conn, id, (sasl_callback_ft *)&chalprompt_cb, &chalprompt_context); 0462 0463 if (ret == SASL_OK && chalprompt_cb) { 0464 ret = chalprompt_cb(chalprompt_context, id, challenge, promptstr, NULL, result, NULL); 0465 if (ret != SASL_OK) 0466 return ret; 0467 0468 if (!*result) { 0469 PARAMERROR(utils); 0470 return SASL_BADPARAM; 0471 } 0472 } 0473 0474 return ret; 0475 } 0476 0477 /* 0478 * Retrieve the client realm. 0479 */ 0480 int _plug_get_realm(const sasl_utils_t *utils, const char **availrealms, const char **realm, sasl_interact_t **prompt_need) 0481 { 0482 int ret = SASL_FAIL; 0483 sasl_getrealm_t *realm_cb; 0484 void *realm_context; 0485 sasl_interact_t *prompt; 0486 0487 *realm = NULL; 0488 0489 /* see if we were given the result in the prompt */ 0490 prompt = _plug_find_prompt(prompt_need, SASL_CB_GETREALM); 0491 if (prompt != NULL) { 0492 /* We prompted, and got.*/ 0493 0494 if (!prompt->result) { 0495 SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_realm"); 0496 return SASL_BADPARAM; 0497 } 0498 0499 *realm = prompt->result; 0500 return SASL_OK; 0501 } 0502 0503 /* Try to get the callback... */ 0504 ret = utils->getcallback(utils->conn, SASL_CB_GETREALM, (sasl_callback_ft *)&realm_cb, &realm_context); 0505 0506 if (ret == SASL_OK && realm_cb) { 0507 ret = realm_cb(realm_context, SASL_CB_GETREALM, availrealms, realm); 0508 if (ret != SASL_OK) 0509 return ret; 0510 0511 if (!*realm) { 0512 PARAMERROR(utils); 0513 return SASL_BADPARAM; 0514 } 0515 } 0516 0517 return ret; 0518 } 0519 0520 /* 0521 * Make the requested prompts. (prompt==NULL means we don't want it) 0522 */ 0523 int _plug_make_prompts(const sasl_utils_t *utils, 0524 sasl_interact_t **prompts_res, 0525 const char *user_prompt, 0526 const char *user_def, 0527 const char *auth_prompt, 0528 const char *auth_def, 0529 const char *pass_prompt, 0530 const char *pass_def, 0531 const char *echo_chal, 0532 const char *echo_prompt, 0533 const char *echo_def, 0534 const char *realm_chal, 0535 const char *realm_prompt, 0536 const char *realm_def) 0537 { 0538 int num = 1; 0539 int alloc_size; 0540 sasl_interact_t *prompts; 0541 0542 if (user_prompt) 0543 num++; 0544 if (auth_prompt) 0545 num++; 0546 if (pass_prompt) 0547 num++; 0548 if (echo_prompt) 0549 num++; 0550 if (realm_prompt) 0551 num++; 0552 0553 if (num == 1) { 0554 SETERROR(utils, "make_prompts() called with no actual prompts"); 0555 return SASL_FAIL; 0556 } 0557 0558 alloc_size = sizeof(sasl_interact_t) * num; 0559 prompts = utils->malloc(alloc_size); 0560 if (!prompts) { 0561 MEMERROR(utils); 0562 return SASL_NOMEM; 0563 } 0564 memset(prompts, 0, alloc_size); 0565 0566 *prompts_res = prompts; 0567 0568 if (user_prompt) { 0569 (prompts)->id = SASL_CB_USER; 0570 (prompts)->challenge = "Authorization Name"; 0571 (prompts)->prompt = user_prompt; 0572 (prompts)->defresult = user_def; 0573 0574 prompts++; 0575 } 0576 0577 if (auth_prompt) { 0578 (prompts)->id = SASL_CB_AUTHNAME; 0579 (prompts)->challenge = "Authentication Name"; 0580 (prompts)->prompt = auth_prompt; 0581 (prompts)->defresult = auth_def; 0582 0583 prompts++; 0584 } 0585 0586 if (pass_prompt) { 0587 (prompts)->id = SASL_CB_PASS; 0588 (prompts)->challenge = "Password"; 0589 (prompts)->prompt = pass_prompt; 0590 (prompts)->defresult = pass_def; 0591 0592 prompts++; 0593 } 0594 0595 if (echo_prompt) { 0596 (prompts)->id = SASL_CB_ECHOPROMPT; 0597 (prompts)->challenge = echo_chal; 0598 (prompts)->prompt = echo_prompt; 0599 (prompts)->defresult = echo_def; 0600 0601 prompts++; 0602 } 0603 0604 if (realm_prompt) { 0605 (prompts)->id = SASL_CB_GETREALM; 0606 (prompts)->challenge = realm_chal; 0607 (prompts)->prompt = realm_prompt; 0608 (prompts)->defresult = realm_def; 0609 0610 prompts++; 0611 } 0612 0613 /* add the ending one */ 0614 (prompts)->id = SASL_CB_LIST_END; 0615 (prompts)->challenge = NULL; 0616 (prompts)->prompt = NULL; 0617 (prompts)->defresult = NULL; 0618 0619 return SASL_OK; 0620 } 0621 0622 void _plug_decode_init(decode_context_t *text, const sasl_utils_t *utils, unsigned int in_maxbuf) 0623 { 0624 memset(text, 0, sizeof(decode_context_t)); 0625 0626 text->utils = utils; 0627 text->needsize = 4; 0628 text->in_maxbuf = in_maxbuf; 0629 } 0630 0631 /* 0632 * Decode as much of the input as possible (possibly none), 0633 * using decode_pkt() to decode individual packets. 0634 */ 0635 int _plug_decode(decode_context_t *text, 0636 const char *input, 0637 unsigned inputlen, 0638 char **output, /* output buffer */ 0639 unsigned *outputsize, /* current size of output buffer */ 0640 unsigned *outputlen, /* length of data in output buffer */ 0641 int (*decode_pkt)(void *rock, const char *input, unsigned inputlen, char **output, unsigned *outputlen), 0642 void *rock) 0643 { 0644 unsigned int tocopy; 0645 unsigned diff; 0646 char *tmp; 0647 unsigned tmplen; 0648 int ret; 0649 0650 *outputlen = 0; 0651 0652 while (inputlen) { /* more input */ 0653 if (text->needsize) { /* need to get the rest of the 4-byte size */ 0654 0655 /* copy as many bytes (up to 4) as we have into size buffer */ 0656 tocopy = (inputlen > text->needsize) ? text->needsize : inputlen; 0657 memcpy(text->sizebuf + 4 - text->needsize, input, tocopy); 0658 text->needsize -= tocopy; 0659 0660 input += tocopy; 0661 inputlen -= tocopy; 0662 0663 if (!text->needsize) { /* we have the entire 4-byte size */ 0664 memcpy(&(text->size), text->sizebuf, 4); 0665 text->size = ntohl(text->size); 0666 0667 if (!text->size) /* should never happen */ 0668 return SASL_FAIL; 0669 0670 if (text->size > text->in_maxbuf) { 0671 text->utils->log(NULL, SASL_LOG_ERR, "encoded packet size too big (%d > %d)", text->size, text->in_maxbuf); 0672 return SASL_FAIL; 0673 } 0674 0675 if (!text->buffer) 0676 text->buffer = text->utils->malloc(text->in_maxbuf); 0677 if (text->buffer == NULL) 0678 return SASL_NOMEM; 0679 0680 text->cursize = 0; 0681 } else { 0682 /* We do NOT have the entire 4-byte size... 0683 * wait for more data */ 0684 return SASL_OK; 0685 } 0686 } 0687 0688 diff = text->size - text->cursize; /* bytes needed for full packet */ 0689 0690 if (inputlen < diff) { /* not a complete packet, need more input */ 0691 memcpy(text->buffer + text->cursize, input, inputlen); 0692 text->cursize += inputlen; 0693 return SASL_OK; 0694 } 0695 0696 /* copy the rest of the packet */ 0697 memcpy(text->buffer + text->cursize, input, diff); 0698 input += diff; 0699 inputlen -= diff; 0700 0701 /* decode the packet (no need to free tmp) */ 0702 ret = decode_pkt(rock, text->buffer, text->size, &tmp, &tmplen); 0703 if (ret != SASL_OK) 0704 return ret; 0705 0706 /* append the decoded packet to the output */ 0707 ret = _plug_buf_alloc(text->utils, output, outputsize, *outputlen + tmplen + 1); /* +1 for NUL */ 0708 if (ret != SASL_OK) 0709 return ret; 0710 0711 memcpy(*output + *outputlen, tmp, tmplen); 0712 *outputlen += tmplen; 0713 0714 /* protect stupid clients */ 0715 *(*output + *outputlen) = '\0'; 0716 0717 /* reset for the next packet */ 0718 text->needsize = 4; 0719 } 0720 0721 return SASL_OK; 0722 } 0723 0724 void _plug_decode_free(decode_context_t *text) 0725 { 0726 if (text->buffer) 0727 text->utils->free(text->buffer); 0728 } 0729 0730 /* returns the realm we should pretend to be in */ 0731 int _plug_parseuser(const sasl_utils_t *utils, char **user, char **realm, const char *user_realm, const char *serverFQDN, const char *input) 0732 { 0733 int ret; 0734 char *r; 0735 0736 if (!user || !serverFQDN) { 0737 PARAMERROR(utils); 0738 return SASL_BADPARAM; 0739 } 0740 0741 r = strchr(input, '@'); 0742 if (!r) { 0743 /* hmmm, the user didn't specify a realm */ 0744 if (user_realm && user_realm[0]) { 0745 ret = _plug_strdup(utils, user_realm, realm, NULL); 0746 } else { 0747 /* Default to serverFQDN */ 0748 ret = _plug_strdup(utils, serverFQDN, realm, NULL); 0749 } 0750 0751 if (ret == SASL_OK) { 0752 ret = _plug_strdup(utils, input, user, NULL); 0753 } 0754 } else { 0755 r++; 0756 ret = _plug_strdup(utils, r, realm, NULL); 0757 *--r = '\0'; 0758 *user = utils->malloc(r - input + 1); 0759 if (*user) { 0760 strncpy(*user, input, r - input + 1); 0761 } else { 0762 MEMERROR(utils); 0763 ret = SASL_NOMEM; 0764 } 0765 *r = '@'; 0766 } 0767 0768 return ret; 0769 } 0770 0771 int _plug_make_fulluser(const sasl_utils_t *utils, char **fulluser, const char *useronly, const char *realm) 0772 { 0773 if (!fulluser || !useronly || !realm) { 0774 PARAMERROR(utils); 0775 return (SASL_BADPARAM); 0776 } 0777 0778 *fulluser = utils->malloc(strlen(useronly) + strlen(realm) + 2); 0779 if (*fulluser == NULL) { 0780 MEMERROR(utils); 0781 return (SASL_NOMEM); 0782 } 0783 0784 strcpy(*fulluser, useronly); 0785 strcat(*fulluser, "@"); 0786 strcat(*fulluser, realm); 0787 0788 return (SASL_OK); 0789 } 0790 0791 char *_plug_get_error_message(const sasl_utils_t *utils, 0792 #ifdef WIN32 0793 DWORD error 0794 #else 0795 int error 0796 #endif 0797 ) 0798 { 0799 char *return_value; 0800 #ifdef WIN32 0801 LPVOID lpMsgBuf; 0802 0803 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0804 NULL, 0805 error, 0806 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ 0807 (LPTSTR)&lpMsgBuf, 0808 0, 0809 NULL); 0810 0811 if (_plug_strdup(utils, lpMsgBuf, &return_value, NULL) != SASL_OK) { 0812 return_value = NULL; 0813 } 0814 0815 LocalFree(lpMsgBuf); 0816 #else /* !WIN32 */ 0817 if (_plug_strdup(utils, strerror(error), &return_value, NULL) != SASL_OK) { 0818 return_value = NULL; 0819 } 0820 #endif /* WIN32 */ 0821 return (return_value); 0822 } 0823 0824 void _plug_snprintf_os_info(char *osbuf, int osbuf_len) 0825 { 0826 #ifdef WIN32 0827 char *sysname; 0828 sysname = "Unknown Windows"; 0829 0830 /* Let's suppose it's still compilable with win2k sdk. So define everythig missing */ 0831 #ifndef _WIN32_WINNT_WINXP 0832 #define _WIN32_WINNT_WINXP 0x0501 0833 #endif 0834 #ifndef _WIN32_WINNT_WS03 0835 #define _WIN32_WINNT_WS03 0x0502 0836 #endif 0837 #ifndef _WIN32_WINNT_WIN6 0838 #define _WIN32_WINNT_WIN6 0x0600 0839 #endif 0840 #ifndef _WIN32_WINNT_VISTA 0841 #define _WIN32_WINNT_VISTA 0x0600 0842 #endif 0843 #ifndef _WIN32_WINNT_WS08 0844 #define _WIN32_WINNT_WS08 0x0600 0845 #endif 0846 #ifndef _WIN32_WINNT_LONGHORN 0847 #define _WIN32_WINNT_LONGHORN 0x0600 0848 #endif 0849 #ifndef _WIN32_WINNT_WIN7 0850 #define _WIN32_WINNT_WIN7 0x0601 0851 #endif 0852 #ifndef _WIN32_WINNT_WIN8 0853 #define _WIN32_WINNT_WIN8 0x0602 0854 #endif 0855 #ifndef _WIN32_WINNT_WINBLUE 0856 #define _WIN32_WINNT_WINBLUE 0x0603 0857 #endif 0858 #ifndef _WIN32_WINNT_WIN10 0859 #define _WIN32_WINNT_WIN10 0x0A00 0860 #endif 0861 0862 /* and use IsWindowsVersionOrGreater instead of convenient wrappers by the same reason */ 0863 if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0)) { 0864 sysname = "Windows 10 or greater"; 0865 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0)) { 0866 sysname = "Windows 8.1"; 0867 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0)) { 0868 sysname = "Windows 8"; 0869 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1)) { 0870 sysname = "Windows 7 SP1"; 0871 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0)) { 0872 sysname = "Windows 7"; 0873 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2)) { 0874 sysname = "Windows Vista SP2"; 0875 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1)) { 0876 sysname = "Windows Vista SP1"; 0877 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0)) { 0878 sysname = "Windows Vista"; 0879 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3)) { 0880 sysname = "Windows XP SP3"; 0881 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2)) { 0882 sysname = "Windows XP SP2"; 0883 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1)) { 0884 sysname = "Windows XP SP1"; 0885 } else if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0)) { 0886 sysname = "Windows XP"; 0887 } 0888 0889 snprintf(osbuf, osbuf_len, "%s", sysname); 0890 0891 #else /* !WIN32 */ 0892 struct utsname os; 0893 0894 uname(&os); 0895 snprintf(osbuf, osbuf_len, "%s %s", os.sysname, os.release); 0896 #endif /* WIN32 */ 0897 } 0898 0899 #if defined(WIN32) 0900 unsigned int plug_sleep(unsigned int seconds) 0901 { 0902 long dwSec = seconds * 1000; 0903 Sleep(dwSec); 0904 return 0; 0905 } 0906 #endif