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