Return to isakmp_xauth.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
1.1 ! misho 1: /* $NetBSD: isakmp_xauth.c,v 1.22 2011/03/14 15:50:36 vanhu Exp $ */ ! 2: ! 3: /* Id: isakmp_xauth.c,v 1.38 2006/08/22 18:17:17 manubsd Exp */ ! 4: ! 5: /* ! 6: * Copyright (C) 2004-2005 Emmanuel Dreyfus ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. Neither the name of the project nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: */ ! 33: ! 34: #include "config.h" ! 35: ! 36: #include <sys/types.h> ! 37: #include <sys/param.h> ! 38: #include <sys/socket.h> ! 39: #include <sys/queue.h> ! 40: ! 41: #include <netinet/in.h> ! 42: ! 43: #include <assert.h> ! 44: #include <stdlib.h> ! 45: #include <stdio.h> ! 46: #include <string.h> ! 47: #include <errno.h> ! 48: #include <pwd.h> ! 49: #include <grp.h> ! 50: #if TIME_WITH_SYS_TIME ! 51: # include <sys/time.h> ! 52: # include <time.h> ! 53: #else ! 54: # if HAVE_SYS_TIME_H ! 55: # include <sys/time.h> ! 56: # else ! 57: # include <time.h> ! 58: # endif ! 59: #endif ! 60: #include <netdb.h> ! 61: #ifdef HAVE_UNISTD_H ! 62: #include <unistd.h> ! 63: #endif ! 64: #include <ctype.h> ! 65: #include <resolv.h> ! 66: ! 67: #ifdef HAVE_SHADOW_H ! 68: #include <shadow.h> ! 69: #endif ! 70: ! 71: #include "var.h" ! 72: #include "misc.h" ! 73: #include "vmbuf.h" ! 74: #include "plog.h" ! 75: #include "sockmisc.h" ! 76: #include "schedule.h" ! 77: #include "debug.h" ! 78: ! 79: #include "crypto_openssl.h" ! 80: #include "isakmp_var.h" ! 81: #include "isakmp.h" ! 82: #include "admin.h" ! 83: #include "privsep.h" ! 84: #include "evt.h" ! 85: #include "handler.h" ! 86: #include "throttle.h" ! 87: #include "remoteconf.h" ! 88: #include "isakmp_inf.h" ! 89: #include "isakmp_xauth.h" ! 90: #include "isakmp_unity.h" ! 91: #include "isakmp_cfg.h" ! 92: #include "strnames.h" ! 93: #include "ipsec_doi.h" ! 94: #include "remoteconf.h" ! 95: #include "localconf.h" ! 96: ! 97: #ifdef HAVE_LIBRADIUS ! 98: #include <radlib.h> ! 99: struct rad_handle *radius_auth_state = NULL; ! 100: struct rad_handle *radius_acct_state = NULL; ! 101: struct xauth_rad_config xauth_rad_config; ! 102: #endif ! 103: ! 104: #ifdef HAVE_LIBPAM ! 105: #include <security/pam_appl.h> ! 106: ! 107: static char *PAM_usr = NULL; ! 108: static char *PAM_pwd = NULL; ! 109: static int PAM_conv(int, const struct pam_message **, ! 110: struct pam_response **, void *); ! 111: static struct pam_conv PAM_chat = { &PAM_conv, NULL }; ! 112: #endif ! 113: ! 114: #ifdef HAVE_LIBLDAP ! 115: #include "ldap.h" ! 116: #include <arpa/inet.h> ! 117: struct xauth_ldap_config xauth_ldap_config; ! 118: #endif ! 119: ! 120: void ! 121: xauth_sendreq(iph1) ! 122: struct ph1handle *iph1; ! 123: { ! 124: vchar_t *buffer; ! 125: struct isakmp_pl_attr *attr; ! 126: struct isakmp_data *typeattr; ! 127: struct isakmp_data *usrattr; ! 128: struct isakmp_data *pwdattr; ! 129: struct xauth_state *xst = &iph1->mode_cfg->xauth; ! 130: size_t tlen; ! 131: ! 132: /* Status checks */ ! 133: if (iph1->status < PHASE1ST_ESTABLISHED) { ! 134: plog(LLV_ERROR, LOCATION, NULL, ! 135: "Xauth request while phase 1 is not completed\n"); ! 136: return; ! 137: } ! 138: ! 139: if (xst->status != XAUTHST_NOTYET) { ! 140: plog(LLV_ERROR, LOCATION, NULL, ! 141: "Xauth request whith Xauth state %d\n", xst->status); ! 142: return; ! 143: } ! 144: ! 145: plog(LLV_INFO, LOCATION, NULL, "Sending Xauth request\n"); ! 146: ! 147: tlen = sizeof(*attr) + ! 148: + sizeof(*typeattr) + ! 149: + sizeof(*usrattr) + ! 150: + sizeof(*pwdattr); ! 151: ! 152: if ((buffer = vmalloc(tlen)) == NULL) { ! 153: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate buffer\n"); ! 154: return; ! 155: } ! 156: ! 157: attr = (struct isakmp_pl_attr *)buffer->v; ! 158: memset(attr, 0, tlen); ! 159: ! 160: attr->h.len = htons(tlen); ! 161: attr->type = ISAKMP_CFG_REQUEST; ! 162: attr->id = htons(eay_random()); ! 163: ! 164: typeattr = (struct isakmp_data *)(attr + 1); ! 165: typeattr->type = htons(XAUTH_TYPE | ISAKMP_GEN_TV); ! 166: typeattr->lorv = htons(XAUTH_TYPE_GENERIC); ! 167: ! 168: usrattr = (struct isakmp_data *)(typeattr + 1); ! 169: usrattr->type = htons(XAUTH_USER_NAME | ISAKMP_GEN_TLV); ! 170: usrattr->lorv = htons(0); ! 171: ! 172: pwdattr = (struct isakmp_data *)(usrattr + 1); ! 173: pwdattr->type = htons(XAUTH_USER_PASSWORD | ISAKMP_GEN_TLV); ! 174: pwdattr->lorv = htons(0); ! 175: ! 176: isakmp_cfg_send(iph1, buffer, ! 177: ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1); ! 178: ! 179: vfree(buffer); ! 180: ! 181: xst->status = XAUTHST_REQSENT; ! 182: ! 183: return; ! 184: } ! 185: ! 186: int ! 187: xauth_attr_reply(iph1, attr, id) ! 188: struct ph1handle *iph1; ! 189: struct isakmp_data *attr; ! 190: int id; ! 191: { ! 192: char **outlet = NULL; ! 193: size_t alen = 0; ! 194: int type; ! 195: struct xauth_state *xst = &iph1->mode_cfg->xauth; ! 196: ! 197: if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { ! 198: plog(LLV_ERROR, LOCATION, NULL, ! 199: "Xauth reply but peer did not declare " ! 200: "itself as Xauth capable\n"); ! 201: return -1; ! 202: } ! 203: ! 204: if (xst->status != XAUTHST_REQSENT) { ! 205: plog(LLV_ERROR, LOCATION, NULL, ! 206: "Xauth reply while Xauth state is %d\n", xst->status); ! 207: return -1; ! 208: } ! 209: ! 210: type = ntohs(attr->type) & ~ISAKMP_GEN_MASK; ! 211: switch (type) { ! 212: case XAUTH_TYPE: ! 213: switch (ntohs(attr->lorv)) { ! 214: case XAUTH_TYPE_GENERIC: ! 215: xst->authtype = XAUTH_TYPE_GENERIC; ! 216: break; ! 217: default: ! 218: plog(LLV_WARNING, LOCATION, NULL, ! 219: "Unexpected authentication type %d\n", ! 220: ntohs(type)); ! 221: return -1; ! 222: } ! 223: break; ! 224: ! 225: case XAUTH_USER_NAME: ! 226: outlet = &xst->authdata.generic.usr; ! 227: break; ! 228: ! 229: case XAUTH_USER_PASSWORD: ! 230: outlet = &xst->authdata.generic.pwd; ! 231: break; ! 232: ! 233: default: ! 234: plog(LLV_WARNING, LOCATION, NULL, ! 235: "ignored Xauth attribute %d\n", type); ! 236: break; ! 237: } ! 238: ! 239: if (outlet != NULL) { ! 240: alen = ntohs(attr->lorv); ! 241: ! 242: if ((*outlet = racoon_malloc(alen + 1)) == NULL) { ! 243: plog(LLV_ERROR, LOCATION, NULL, ! 244: "Cannot allocate memory for Xauth Data\n"); ! 245: return -1; ! 246: } ! 247: ! 248: memcpy(*outlet, attr + 1, alen); ! 249: (*outlet)[alen] = '\0'; ! 250: outlet = NULL; ! 251: } ! 252: ! 253: ! 254: if ((xst->authdata.generic.usr != NULL) && ! 255: (xst->authdata.generic.pwd != NULL)) { ! 256: int port; ! 257: int res; ! 258: char *usr = xst->authdata.generic.usr; ! 259: char *pwd = xst->authdata.generic.pwd; ! 260: time_t throttle_delay = 0; ! 261: ! 262: #if 0 /* Real debug, don't do that at home */ ! 263: plog(LLV_DEBUG, LOCATION, NULL, ! 264: "Got username \"%s\", password \"%s\"\n", usr, pwd); ! 265: #endif ! 266: strncpy(iph1->mode_cfg->login, usr, LOGINLEN); ! 267: iph1->mode_cfg->login[LOGINLEN] = '\0'; ! 268: ! 269: res = -1; ! 270: if ((port = isakmp_cfg_getport(iph1)) == -1) { ! 271: plog(LLV_ERROR, LOCATION, NULL, ! 272: "Port pool depleted\n"); ! 273: goto skip_auth; ! 274: } ! 275: ! 276: switch (isakmp_cfg_config.authsource) { ! 277: case ISAKMP_CFG_AUTH_SYSTEM: ! 278: res = privsep_xauth_login_system(usr, pwd); ! 279: break; ! 280: #ifdef HAVE_LIBRADIUS ! 281: case ISAKMP_CFG_AUTH_RADIUS: ! 282: res = xauth_login_radius(iph1, usr, pwd); ! 283: break; ! 284: #endif ! 285: #ifdef HAVE_LIBPAM ! 286: case ISAKMP_CFG_AUTH_PAM: ! 287: res = privsep_xauth_login_pam(iph1->mode_cfg->port, ! 288: iph1->remote, usr, pwd); ! 289: break; ! 290: #endif ! 291: #ifdef HAVE_LIBLDAP ! 292: case ISAKMP_CFG_AUTH_LDAP: ! 293: res = xauth_login_ldap(iph1, usr, pwd); ! 294: break; ! 295: #endif ! 296: default: ! 297: plog(LLV_ERROR, LOCATION, NULL, ! 298: "Unexpected authentication source\n"); ! 299: res = -1; ! 300: break; ! 301: } ! 302: ! 303: /* ! 304: * Optional group authentication ! 305: */ ! 306: if (!res && (isakmp_cfg_config.groupcount)) ! 307: res = group_check(iph1, ! 308: isakmp_cfg_config.grouplist, ! 309: isakmp_cfg_config.groupcount); ! 310: ! 311: /* ! 312: * On failure, throttle the connexion for the remote host ! 313: * in order to make password attacks more difficult. ! 314: */ ! 315: throttle_delay = throttle_host(iph1->remote, res); ! 316: if (throttle_delay > 0) { ! 317: char *str; ! 318: ! 319: str = saddrwop2str(iph1->remote); ! 320: ! 321: plog(LLV_ERROR, LOCATION, NULL, ! 322: "Throttling in action for %s: delay %lds\n", ! 323: str, (unsigned long)throttle_delay); ! 324: res = -1; ! 325: } else { ! 326: throttle_delay = 0; ! 327: } ! 328: ! 329: skip_auth: ! 330: if (throttle_delay != 0) { ! 331: struct xauth_reply_arg *xra; ! 332: ! 333: if ((xra = racoon_calloc(1, sizeof(*xra))) == NULL) { ! 334: plog(LLV_ERROR, LOCATION, NULL, ! 335: "malloc failed, bypass throttling\n"); ! 336: return xauth_reply(iph1, port, id, res); ! 337: } ! 338: ! 339: /* ! 340: * We need to store the ph1, but it might have ! 341: * disapeared when xauth_reply is called, so ! 342: * store the index instead. ! 343: */ ! 344: xra->index = iph1->index; ! 345: xra->port = port; ! 346: xra->id = id; ! 347: xra->res = res; ! 348: sched_schedule(&xra->sc, throttle_delay, ! 349: xauth_reply_stub); ! 350: } else { ! 351: return xauth_reply(iph1, port, id, res); ! 352: } ! 353: } ! 354: ! 355: return 0; ! 356: } ! 357: ! 358: void ! 359: xauth_reply_stub(sc) ! 360: struct sched *sc; ! 361: { ! 362: struct xauth_reply_arg *xra = container_of(sc, struct xauth_reply_arg, sc); ! 363: struct ph1handle *iph1; ! 364: ! 365: if ((iph1 = getph1byindex(&xra->index)) != NULL) ! 366: (void)xauth_reply(iph1, xra->port, xra->id, xra->res); ! 367: else ! 368: plog(LLV_ERROR, LOCATION, NULL, ! 369: "Delayed Xauth reply: phase 1 no longer exists.\n"); ! 370: ! 371: racoon_free(xra); ! 372: } ! 373: ! 374: int ! 375: xauth_reply(iph1, port, id, res) ! 376: struct ph1handle *iph1; ! 377: int port; ! 378: int id; ! 379: { ! 380: struct xauth_state *xst = &iph1->mode_cfg->xauth; ! 381: char *usr = xst->authdata.generic.usr; ! 382: ! 383: if (res != 0) { ! 384: if (port != -1) ! 385: isakmp_cfg_putport(iph1, port); ! 386: ! 387: plog(LLV_INFO, LOCATION, NULL, ! 388: "login failed for user \"%s\"\n", usr); ! 389: ! 390: xauth_sendstatus(iph1, XAUTH_STATUS_FAIL, id); ! 391: xst->status = XAUTHST_NOTYET; ! 392: ! 393: /* Delete Phase 1 SA */ ! 394: if (iph1->status >= PHASE1ST_ESTABLISHED) ! 395: isakmp_info_send_d1(iph1); ! 396: remph1(iph1); ! 397: delph1(iph1); ! 398: ! 399: return -1; ! 400: } ! 401: ! 402: xst->status = XAUTHST_OK; ! 403: plog(LLV_INFO, LOCATION, NULL, ! 404: "login succeeded for user \"%s\"\n", usr); ! 405: ! 406: xauth_sendstatus(iph1, XAUTH_STATUS_OK, id); ! 407: ! 408: return 0; ! 409: } ! 410: ! 411: void ! 412: xauth_sendstatus(iph1, status, id) ! 413: struct ph1handle *iph1; ! 414: int status; ! 415: int id; ! 416: { ! 417: vchar_t *buffer; ! 418: struct isakmp_pl_attr *attr; ! 419: struct isakmp_data *stattr; ! 420: size_t tlen; ! 421: ! 422: tlen = sizeof(*attr) + ! 423: + sizeof(*stattr); ! 424: ! 425: if ((buffer = vmalloc(tlen)) == NULL) { ! 426: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate buffer\n"); ! 427: return; ! 428: } ! 429: ! 430: attr = (struct isakmp_pl_attr *)buffer->v; ! 431: memset(attr, 0, tlen); ! 432: ! 433: attr->h.len = htons(tlen); ! 434: attr->type = ISAKMP_CFG_SET; ! 435: attr->id = htons(id); ! 436: ! 437: stattr = (struct isakmp_data *)(attr + 1); ! 438: stattr->type = htons(XAUTH_STATUS | ISAKMP_GEN_TV); ! 439: stattr->lorv = htons(status); ! 440: ! 441: isakmp_cfg_send(iph1, buffer, ! 442: ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1); ! 443: ! 444: vfree(buffer); ! 445: ! 446: return; ! 447: } ! 448: ! 449: #ifdef HAVE_LIBRADIUS ! 450: int ! 451: xauth_radius_init_conf(int free) ! 452: { ! 453: /* free radius config resources */ ! 454: if (free) { ! 455: int i; ! 456: for (i = 0; i < xauth_rad_config.auth_server_count; i++) { ! 457: vfree(xauth_rad_config.auth_server_list[i].host); ! 458: vfree(xauth_rad_config.auth_server_list[i].secret); ! 459: } ! 460: for (i = 0; i < xauth_rad_config.acct_server_count; i++) { ! 461: vfree(xauth_rad_config.acct_server_list[i].host); ! 462: vfree(xauth_rad_config.acct_server_list[i].secret); ! 463: } ! 464: if (radius_auth_state != NULL) ! 465: rad_close(radius_auth_state); ! 466: if (radius_acct_state != NULL) ! 467: rad_close(radius_acct_state); ! 468: } ! 469: ! 470: /* initialize radius config */ ! 471: memset(&xauth_rad_config, 0, sizeof(xauth_rad_config)); ! 472: return 0; ! 473: } ! 474: ! 475: int ! 476: xauth_radius_init(void) ! 477: { ! 478: /* For first time use, initialize Radius */ ! 479: if ((isakmp_cfg_config.authsource == ISAKMP_CFG_AUTH_RADIUS) && ! 480: (radius_auth_state == NULL)) { ! 481: if ((radius_auth_state = rad_auth_open()) == NULL) { ! 482: plog(LLV_ERROR, LOCATION, NULL, ! 483: "Cannot init libradius\n"); ! 484: return -1; ! 485: } ! 486: ! 487: int auth_count = xauth_rad_config.auth_server_count; ! 488: int auth_added = 0; ! 489: if (auth_count) { ! 490: int i; ! 491: for (i = 0; i < auth_count; i++) { ! 492: if(!rad_add_server( ! 493: radius_auth_state, ! 494: xauth_rad_config.auth_server_list[i].host->v, ! 495: xauth_rad_config.auth_server_list[i].port, ! 496: xauth_rad_config.auth_server_list[i].secret->v, ! 497: xauth_rad_config.timeout, ! 498: xauth_rad_config.retries )) ! 499: auth_added++; ! 500: else ! 501: plog(LLV_WARNING, LOCATION, NULL, ! 502: "could not add radius auth server %s\n", ! 503: xauth_rad_config.auth_server_list[i].host->v); ! 504: } ! 505: } ! 506: ! 507: if (!auth_added) { ! 508: if (rad_config(radius_auth_state, NULL) != 0) { ! 509: plog(LLV_ERROR, LOCATION, NULL, ! 510: "Cannot open libradius config file: %s\n", ! 511: rad_strerror(radius_auth_state)); ! 512: rad_close(radius_auth_state); ! 513: radius_auth_state = NULL; ! 514: return -1; ! 515: } ! 516: } ! 517: } ! 518: ! 519: if ((isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_RADIUS) && ! 520: (radius_acct_state == NULL)) { ! 521: if ((radius_acct_state = rad_acct_open()) == NULL) { ! 522: plog(LLV_ERROR, LOCATION, NULL, ! 523: "Cannot init libradius\n"); ! 524: return -1; ! 525: } ! 526: ! 527: int acct_count = xauth_rad_config.acct_server_count; ! 528: int acct_added = 0; ! 529: if (acct_count) { ! 530: int i; ! 531: for (i = 0; i < acct_count; i++) { ! 532: if(!rad_add_server( ! 533: radius_acct_state, ! 534: xauth_rad_config.acct_server_list[i].host->v, ! 535: xauth_rad_config.acct_server_list[i].port, ! 536: xauth_rad_config.acct_server_list[i].secret->v, ! 537: xauth_rad_config.timeout, ! 538: xauth_rad_config.retries )) ! 539: acct_added++; ! 540: else ! 541: plog(LLV_WARNING, LOCATION, NULL, ! 542: "could not add radius account server %s\n", ! 543: xauth_rad_config.acct_server_list[i].host->v); ! 544: } ! 545: } ! 546: ! 547: if (!acct_added) { ! 548: if (rad_config(radius_acct_state, NULL) != 0) { ! 549: plog(LLV_ERROR, LOCATION, NULL, ! 550: "Cannot open libradius config file: %s\n", ! 551: rad_strerror(radius_acct_state)); ! 552: rad_close(radius_acct_state); ! 553: radius_acct_state = NULL; ! 554: return -1; ! 555: } ! 556: } ! 557: } ! 558: ! 559: return 0; ! 560: } ! 561: ! 562: int ! 563: xauth_login_radius(iph1, usr, pwd) ! 564: struct ph1handle *iph1; ! 565: char *usr; ! 566: char *pwd; ! 567: { ! 568: int res; ! 569: const void *data; ! 570: size_t len; ! 571: int type; ! 572: ! 573: if (rad_create_request(radius_auth_state, RAD_ACCESS_REQUEST) != 0) { ! 574: plog(LLV_ERROR, LOCATION, NULL, ! 575: "rad_create_request failed: %s\n", ! 576: rad_strerror(radius_auth_state)); ! 577: return -1; ! 578: } ! 579: ! 580: if (rad_put_string(radius_auth_state, RAD_USER_NAME, usr) != 0) { ! 581: plog(LLV_ERROR, LOCATION, NULL, ! 582: "rad_put_string failed: %s\n", ! 583: rad_strerror(radius_auth_state)); ! 584: return -1; ! 585: } ! 586: ! 587: if (rad_put_string(radius_auth_state, RAD_USER_PASSWORD, pwd) != 0) { ! 588: plog(LLV_ERROR, LOCATION, NULL, ! 589: "rad_put_string failed: %s\n", ! 590: rad_strerror(radius_auth_state)); ! 591: return -1; ! 592: } ! 593: ! 594: if (isakmp_cfg_radius_common(radius_auth_state, iph1->mode_cfg->port) != 0) ! 595: return -1; ! 596: ! 597: switch (res = rad_send_request(radius_auth_state)) { ! 598: case RAD_ACCESS_ACCEPT: ! 599: while ((type = rad_get_attr(radius_auth_state, &data, &len)) != 0) { ! 600: switch (type) { ! 601: case RAD_FRAMED_IP_ADDRESS: ! 602: iph1->mode_cfg->addr4 = rad_cvt_addr(data); ! 603: iph1->mode_cfg->flags ! 604: |= ISAKMP_CFG_ADDR4_EXTERN; ! 605: break; ! 606: ! 607: case RAD_FRAMED_IP_NETMASK: ! 608: iph1->mode_cfg->mask4 = rad_cvt_addr(data); ! 609: iph1->mode_cfg->flags ! 610: |= ISAKMP_CFG_MASK4_EXTERN; ! 611: break; ! 612: ! 613: default: ! 614: plog(LLV_INFO, LOCATION, NULL, ! 615: "Unexpected attribute: %d\n", type); ! 616: break; ! 617: } ! 618: } ! 619: ! 620: return 0; ! 621: break; ! 622: ! 623: case RAD_ACCESS_REJECT: ! 624: return -1; ! 625: break; ! 626: ! 627: case -1: ! 628: plog(LLV_ERROR, LOCATION, NULL, ! 629: "rad_send_request failed: %s\n", ! 630: rad_strerror(radius_auth_state)); ! 631: return -1; ! 632: break; ! 633: default: ! 634: plog(LLV_ERROR, LOCATION, NULL, ! 635: "rad_send_request returned %d\n", res); ! 636: return -1; ! 637: break; ! 638: } ! 639: ! 640: return -1; ! 641: } ! 642: #endif ! 643: ! 644: #ifdef HAVE_LIBPAM ! 645: static int ! 646: PAM_conv(msg_count, msg, rsp, dontcare) ! 647: int msg_count; ! 648: const struct pam_message **msg; ! 649: struct pam_response **rsp; ! 650: void *dontcare; ! 651: { ! 652: int i; ! 653: int replies = 0; ! 654: struct pam_response *reply = NULL; ! 655: ! 656: if ((reply = racoon_malloc(sizeof(*reply) * msg_count)) == NULL) ! 657: return PAM_CONV_ERR; ! 658: bzero(reply, sizeof(*reply) * msg_count); ! 659: ! 660: for (i = 0; i < msg_count; i++) { ! 661: switch (msg[i]->msg_style) { ! 662: case PAM_PROMPT_ECHO_ON: ! 663: /* Send the username, libpam frees resp */ ! 664: reply[i].resp_retcode = PAM_SUCCESS; ! 665: if ((reply[i].resp = strdup(PAM_usr)) == NULL) { ! 666: plog(LLV_ERROR, LOCATION, ! 667: NULL, "strdup failed\n"); ! 668: exit(1); ! 669: } ! 670: break; ! 671: ! 672: case PAM_PROMPT_ECHO_OFF: ! 673: /* Send the password, libpam frees resp */ ! 674: reply[i].resp_retcode = PAM_SUCCESS; ! 675: if ((reply[i].resp = strdup(PAM_pwd)) == NULL) { ! 676: plog(LLV_ERROR, LOCATION, ! 677: NULL, "strdup failed\n"); ! 678: exit(1); ! 679: } ! 680: break; ! 681: ! 682: case PAM_TEXT_INFO: ! 683: case PAM_ERROR_MSG: ! 684: reply[i].resp_retcode = PAM_SUCCESS; ! 685: reply[i].resp = NULL; ! 686: break; ! 687: ! 688: default: ! 689: if (reply != NULL) ! 690: racoon_free(reply); ! 691: return PAM_CONV_ERR; ! 692: break; ! 693: } ! 694: } ! 695: ! 696: if (reply != NULL) ! 697: *rsp = reply; ! 698: ! 699: return PAM_SUCCESS; ! 700: } ! 701: ! 702: int ! 703: xauth_login_pam(port, raddr, usr, pwd) ! 704: int port; ! 705: struct sockaddr *raddr; ! 706: char *usr; ! 707: char *pwd; ! 708: { ! 709: int error; ! 710: int res; ! 711: const void *data; ! 712: size_t len; ! 713: int type; ! 714: char *remote = NULL; ! 715: pam_handle_t *pam = NULL; ! 716: ! 717: if (isakmp_cfg_config.port_pool == NULL) { ! 718: plog(LLV_ERROR, LOCATION, NULL, ! 719: "isakmp_cfg_config.port_pool == NULL\n"); ! 720: return -1; ! 721: } ! 722: ! 723: if ((error = pam_start("racoon", usr, ! 724: &PAM_chat, &isakmp_cfg_config.port_pool[port].pam)) != 0) { ! 725: if (isakmp_cfg_config.port_pool[port].pam == NULL) { ! 726: plog(LLV_ERROR, LOCATION, NULL, "pam_start failed\n"); ! 727: return -1; ! 728: } else { ! 729: plog(LLV_ERROR, LOCATION, NULL, ! 730: "pam_start failed: %s\n", ! 731: pam_strerror(isakmp_cfg_config.port_pool[port].pam, ! 732: error)); ! 733: goto out; ! 734: } ! 735: } ! 736: pam = isakmp_cfg_config.port_pool[port].pam; ! 737: ! 738: if ((remote = strdup(saddrwop2str(raddr))) == NULL) { ! 739: plog(LLV_ERROR, LOCATION, NULL, ! 740: "cannot allocate memory: %s\n", strerror(errno)); ! 741: goto out; ! 742: } ! 743: ! 744: if ((error = pam_set_item(pam, PAM_RHOST, remote)) != 0) { ! 745: plog(LLV_ERROR, LOCATION, NULL, ! 746: "pam_set_item failed: %s\n", ! 747: pam_strerror(pam, error)); ! 748: goto out; ! 749: } ! 750: ! 751: if ((error = pam_set_item(pam, PAM_RUSER, usr)) != 0) { ! 752: plog(LLV_ERROR, LOCATION, NULL, ! 753: "pam_set_item failed: %s\n", ! 754: pam_strerror(pam, error)); ! 755: goto out; ! 756: } ! 757: ! 758: PAM_usr = usr; ! 759: PAM_pwd = pwd; ! 760: error = pam_authenticate(pam, 0); ! 761: PAM_usr = NULL; ! 762: PAM_pwd = NULL; ! 763: if (error != 0) { ! 764: plog(LLV_ERROR, LOCATION, NULL, ! 765: "pam_authenticate failed: %s\n", ! 766: pam_strerror(pam, error)); ! 767: goto out; ! 768: } ! 769: ! 770: if ((error = pam_acct_mgmt(pam, 0)) != 0) { ! 771: plog(LLV_ERROR, LOCATION, NULL, ! 772: "pam_acct_mgmt failed: %s\n", ! 773: pam_strerror(pam, error)); ! 774: goto out; ! 775: } ! 776: ! 777: if ((error = pam_setcred(pam, 0)) != 0) { ! 778: plog(LLV_ERROR, LOCATION, NULL, ! 779: "pam_setcred failed: %s\n", ! 780: pam_strerror(pam, error)); ! 781: goto out; ! 782: } ! 783: ! 784: if (remote != NULL) ! 785: free(remote); ! 786: ! 787: return 0; ! 788: ! 789: out: ! 790: pam_end(pam, error); ! 791: isakmp_cfg_config.port_pool[port].pam = NULL; ! 792: if (remote != NULL) ! 793: free(remote); ! 794: return -1; ! 795: } ! 796: #endif ! 797: ! 798: #ifdef HAVE_LIBLDAP ! 799: int ! 800: xauth_ldap_init_conf(void) ! 801: { ! 802: int tmplen; ! 803: int error = -1; ! 804: ! 805: xauth_ldap_config.pver = 3; ! 806: xauth_ldap_config.host = NULL; ! 807: xauth_ldap_config.port = LDAP_PORT; ! 808: xauth_ldap_config.base = NULL; ! 809: xauth_ldap_config.subtree = 0; ! 810: xauth_ldap_config.bind_dn = NULL; ! 811: xauth_ldap_config.bind_pw = NULL; ! 812: xauth_ldap_config.auth_type = LDAP_AUTH_SIMPLE; ! 813: xauth_ldap_config.attr_user = NULL; ! 814: xauth_ldap_config.attr_addr = NULL; ! 815: xauth_ldap_config.attr_mask = NULL; ! 816: xauth_ldap_config.attr_group = NULL; ! 817: xauth_ldap_config.attr_member = NULL; ! 818: ! 819: /* set default host */ ! 820: tmplen = strlen(LDAP_DFLT_HOST); ! 821: xauth_ldap_config.host = vmalloc(tmplen); ! 822: if (xauth_ldap_config.host == NULL) ! 823: goto out; ! 824: memcpy(xauth_ldap_config.host->v, LDAP_DFLT_HOST, tmplen); ! 825: ! 826: /* set default user naming attribute */ ! 827: tmplen = strlen(LDAP_DFLT_USER); ! 828: xauth_ldap_config.attr_user = vmalloc(tmplen); ! 829: if (xauth_ldap_config.attr_user == NULL) ! 830: goto out; ! 831: memcpy(xauth_ldap_config.attr_user->v, LDAP_DFLT_USER, tmplen); ! 832: ! 833: /* set default address attribute */ ! 834: tmplen = strlen(LDAP_DFLT_ADDR); ! 835: xauth_ldap_config.attr_addr = vmalloc(tmplen); ! 836: if (xauth_ldap_config.attr_addr == NULL) ! 837: goto out; ! 838: memcpy(xauth_ldap_config.attr_addr->v, LDAP_DFLT_ADDR, tmplen); ! 839: ! 840: /* set default netmask attribute */ ! 841: tmplen = strlen(LDAP_DFLT_MASK); ! 842: xauth_ldap_config.attr_mask = vmalloc(tmplen); ! 843: if (xauth_ldap_config.attr_mask == NULL) ! 844: goto out; ! 845: memcpy(xauth_ldap_config.attr_mask->v, LDAP_DFLT_MASK, tmplen); ! 846: ! 847: /* set default group naming attribute */ ! 848: tmplen = strlen(LDAP_DFLT_GROUP); ! 849: xauth_ldap_config.attr_group = vmalloc(tmplen); ! 850: if (xauth_ldap_config.attr_group == NULL) ! 851: goto out; ! 852: memcpy(xauth_ldap_config.attr_group->v, LDAP_DFLT_GROUP, tmplen); ! 853: ! 854: /* set default member attribute */ ! 855: tmplen = strlen(LDAP_DFLT_MEMBER); ! 856: xauth_ldap_config.attr_member = vmalloc(tmplen); ! 857: if (xauth_ldap_config.attr_member == NULL) ! 858: goto out; ! 859: memcpy(xauth_ldap_config.attr_member->v, LDAP_DFLT_MEMBER, tmplen); ! 860: ! 861: error = 0; ! 862: out: ! 863: if (error != 0) ! 864: plog(LLV_ERROR, LOCATION, NULL, "cannot allocate memory\n"); ! 865: ! 866: return error; ! 867: } ! 868: ! 869: int ! 870: xauth_login_ldap(iph1, usr, pwd) ! 871: struct ph1handle *iph1; ! 872: char *usr; ! 873: char *pwd; ! 874: { ! 875: int rtn = -1; ! 876: int res = -1; ! 877: LDAP *ld = NULL; ! 878: LDAPMessage *lr = NULL; ! 879: LDAPMessage *le = NULL; ! 880: struct berval cred; ! 881: struct berval **bv = NULL; ! 882: struct timeval timeout; ! 883: char *init = NULL; ! 884: char *filter = NULL; ! 885: char *atlist[3]; ! 886: char *basedn = NULL; ! 887: char *userdn = NULL; ! 888: int tmplen = 0; ! 889: int ecount = 0; ! 890: int scope = LDAP_SCOPE_ONE; ! 891: ! 892: atlist[0] = NULL; ! 893: atlist[1] = NULL; ! 894: atlist[2] = NULL; ! 895: ! 896: /* build our initialization url */ ! 897: tmplen = strlen("ldap://:") + 17; ! 898: tmplen += strlen(xauth_ldap_config.host->v); ! 899: init = racoon_malloc(tmplen); ! 900: if (init == NULL) { ! 901: plog(LLV_ERROR, LOCATION, NULL, ! 902: "unable to alloc ldap init url\n"); ! 903: goto ldap_end; ! 904: } ! 905: sprintf(init,"ldap://%s:%d", ! 906: xauth_ldap_config.host->v, ! 907: xauth_ldap_config.port ); ! 908: ! 909: /* initialize the ldap handle */ ! 910: res = ldap_initialize(&ld, init); ! 911: if (res != LDAP_SUCCESS) { ! 912: plog(LLV_ERROR, LOCATION, NULL, ! 913: "ldap_initialize failed: %s\n", ! 914: ldap_err2string(res)); ! 915: goto ldap_end; ! 916: } ! 917: ! 918: /* initialize the protocol version */ ! 919: ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, ! 920: &xauth_ldap_config.pver); ! 921: ! 922: /* ! 923: * attempt to bind to the ldap server. ! 924: * default to anonymous bind unless a ! 925: * user dn and password has been ! 926: * specified in our configuration ! 927: */ ! 928: if ((xauth_ldap_config.bind_dn != NULL)&& ! 929: (xauth_ldap_config.bind_pw != NULL)) ! 930: { ! 931: cred.bv_val = xauth_ldap_config.bind_pw->v; ! 932: cred.bv_len = strlen( cred.bv_val ); ! 933: res = ldap_sasl_bind_s(ld, ! 934: xauth_ldap_config.bind_dn->v, NULL, &cred, ! 935: NULL, NULL, NULL); ! 936: } ! 937: else ! 938: { ! 939: res = ldap_sasl_bind_s(ld, ! 940: NULL, NULL, NULL, ! 941: NULL, NULL, NULL); ! 942: } ! 943: ! 944: if (res!=LDAP_SUCCESS) { ! 945: plog(LLV_ERROR, LOCATION, NULL, ! 946: "ldap_sasl_bind_s (search) failed: %s\n", ! 947: ldap_err2string(res)); ! 948: goto ldap_end; ! 949: } ! 950: ! 951: /* build an ldap user search filter */ ! 952: tmplen = strlen(xauth_ldap_config.attr_user->v); ! 953: tmplen += 1; ! 954: tmplen += strlen(usr); ! 955: tmplen += 1; ! 956: filter = racoon_malloc(tmplen); ! 957: if (filter == NULL) { ! 958: plog(LLV_ERROR, LOCATION, NULL, ! 959: "unable to alloc ldap search filter buffer\n"); ! 960: goto ldap_end; ! 961: } ! 962: sprintf(filter, "%s=%s", ! 963: xauth_ldap_config.attr_user->v, usr); ! 964: ! 965: /* build our return attribute list */ ! 966: tmplen = strlen(xauth_ldap_config.attr_addr->v) + 1; ! 967: atlist[0] = racoon_malloc(tmplen); ! 968: tmplen = strlen(xauth_ldap_config.attr_mask->v) + 1; ! 969: atlist[1] = racoon_malloc(tmplen); ! 970: if ((atlist[0] == NULL)||(atlist[1] == NULL)) { ! 971: plog(LLV_ERROR, LOCATION, NULL, ! 972: "unable to alloc ldap attrib list buffer\n"); ! 973: goto ldap_end; ! 974: } ! 975: strcpy(atlist[0],xauth_ldap_config.attr_addr->v); ! 976: strcpy(atlist[1],xauth_ldap_config.attr_mask->v); ! 977: ! 978: /* attempt to locate the user dn */ ! 979: if (xauth_ldap_config.base != NULL) ! 980: basedn = xauth_ldap_config.base->v; ! 981: if (xauth_ldap_config.subtree) ! 982: scope = LDAP_SCOPE_SUBTREE; ! 983: timeout.tv_sec = 15; ! 984: timeout.tv_usec = 0; ! 985: res = ldap_search_ext_s(ld, basedn, scope, ! 986: filter, atlist, 0, NULL, NULL, ! 987: &timeout, 2, &lr); ! 988: if (res != LDAP_SUCCESS) { ! 989: plog(LLV_ERROR, LOCATION, NULL, ! 990: "ldap_search_ext_s failed: %s\n", ! 991: ldap_err2string(res)); ! 992: goto ldap_end; ! 993: } ! 994: ! 995: /* check the number of ldap entries returned */ ! 996: ecount = ldap_count_entries(ld, lr); ! 997: if (ecount < 1) { ! 998: plog(LLV_WARNING, LOCATION, NULL, ! 999: "no ldap results for filter \'%s\'\n", ! 1000: filter); ! 1001: goto ldap_end; ! 1002: } ! 1003: if (ecount > 1) { ! 1004: plog(LLV_WARNING, LOCATION, NULL, ! 1005: "multiple (%i) ldap results for filter \'%s\'\n", ! 1006: ecount, filter); ! 1007: } ! 1008: ! 1009: /* obtain the dn from the first result */ ! 1010: le = ldap_first_entry(ld, lr); ! 1011: if (le == NULL) { ! 1012: plog(LLV_ERROR, LOCATION, NULL, ! 1013: "ldap_first_entry failed: invalid entry returned\n"); ! 1014: goto ldap_end; ! 1015: } ! 1016: userdn = ldap_get_dn(ld, le); ! 1017: if (userdn == NULL) { ! 1018: plog(LLV_ERROR, LOCATION, NULL, ! 1019: "ldap_get_dn failed: invalid string returned\n"); ! 1020: goto ldap_end; ! 1021: } ! 1022: ! 1023: /* cache the user dn in the xauth state */ ! 1024: iph1->mode_cfg->xauth.udn = racoon_malloc(strlen(userdn)+1); ! 1025: strcpy(iph1->mode_cfg->xauth.udn,userdn); ! 1026: ! 1027: /* retrieve modecfg address */ ! 1028: bv = ldap_get_values_len(ld, le, xauth_ldap_config.attr_addr->v); ! 1029: if (bv != NULL) { ! 1030: char tmpaddr[16]; ! 1031: /* sanity check for address value */ ! 1032: if ((bv[0]->bv_len < 7)||(bv[0]->bv_len > 15)) { ! 1033: plog(LLV_DEBUG, LOCATION, NULL, ! 1034: "ldap returned invalid modecfg address\n"); ! 1035: ldap_value_free_len(bv); ! 1036: goto ldap_end; ! 1037: } ! 1038: memcpy(tmpaddr,bv[0]->bv_val,bv[0]->bv_len); ! 1039: tmpaddr[bv[0]->bv_len]=0; ! 1040: iph1->mode_cfg->addr4.s_addr = inet_addr(tmpaddr); ! 1041: iph1->mode_cfg->flags |= ISAKMP_CFG_ADDR4_EXTERN; ! 1042: plog(LLV_INFO, LOCATION, NULL, ! 1043: "ldap returned modecfg address %s\n", tmpaddr); ! 1044: ldap_value_free_len(bv); ! 1045: } ! 1046: ! 1047: /* retrieve modecfg netmask */ ! 1048: bv = ldap_get_values_len(ld, le, xauth_ldap_config.attr_mask->v); ! 1049: if (bv != NULL) { ! 1050: char tmpmask[16]; ! 1051: /* sanity check for netmask value */ ! 1052: if ((bv[0]->bv_len < 7)||(bv[0]->bv_len > 15)) { ! 1053: plog(LLV_DEBUG, LOCATION, NULL, ! 1054: "ldap returned invalid modecfg netmask\n"); ! 1055: ldap_value_free_len(bv); ! 1056: goto ldap_end; ! 1057: } ! 1058: memcpy(tmpmask,bv[0]->bv_val,bv[0]->bv_len); ! 1059: tmpmask[bv[0]->bv_len]=0; ! 1060: iph1->mode_cfg->mask4.s_addr = inet_addr(tmpmask); ! 1061: iph1->mode_cfg->flags |= ISAKMP_CFG_MASK4_EXTERN; ! 1062: plog(LLV_INFO, LOCATION, NULL, ! 1063: "ldap returned modecfg netmask %s\n", tmpmask); ! 1064: ldap_value_free_len(bv); ! 1065: } ! 1066: ! 1067: /* ! 1068: * finally, use the dn and the xauth ! 1069: * password to check the users given ! 1070: * credentials by attempting to bind ! 1071: * to the ldap server ! 1072: */ ! 1073: plog(LLV_INFO, LOCATION, NULL, ! 1074: "attempting ldap bind for dn \'%s\'\n", userdn); ! 1075: cred.bv_val = pwd; ! 1076: cred.bv_len = strlen( cred.bv_val ); ! 1077: res = ldap_sasl_bind_s(ld, ! 1078: userdn, NULL, &cred, ! 1079: NULL, NULL, NULL); ! 1080: if(res==LDAP_SUCCESS) ! 1081: rtn = 0; ! 1082: ! 1083: ldap_end: ! 1084: ! 1085: /* free ldap resources */ ! 1086: if (userdn != NULL) ! 1087: ldap_memfree(userdn); ! 1088: if (atlist[0] != NULL) ! 1089: racoon_free(atlist[0]); ! 1090: if (atlist[1] != NULL) ! 1091: racoon_free(atlist[1]); ! 1092: if (filter != NULL) ! 1093: racoon_free(filter); ! 1094: if (lr != NULL) ! 1095: ldap_msgfree(lr); ! 1096: if (init != NULL) ! 1097: racoon_free(init); ! 1098: ! 1099: ldap_unbind_ext_s(ld, NULL, NULL); ! 1100: ! 1101: return rtn; ! 1102: } ! 1103: ! 1104: int ! 1105: xauth_group_ldap(udn, grp) ! 1106: char * udn; ! 1107: char * grp; ! 1108: { ! 1109: int rtn = -1; ! 1110: int res = -1; ! 1111: LDAP *ld = NULL; ! 1112: LDAPMessage *lr = NULL; ! 1113: LDAPMessage *le = NULL; ! 1114: struct berval cred; ! 1115: struct timeval timeout; ! 1116: char *init = NULL; ! 1117: char *filter = NULL; ! 1118: char *basedn = NULL; ! 1119: char *groupdn = NULL; ! 1120: int tmplen = 0; ! 1121: int ecount = 0; ! 1122: int scope = LDAP_SCOPE_ONE; ! 1123: ! 1124: /* build our initialization url */ ! 1125: tmplen = strlen("ldap://:") + 17; ! 1126: tmplen += strlen(xauth_ldap_config.host->v); ! 1127: init = racoon_malloc(tmplen); ! 1128: if (init == NULL) { ! 1129: plog(LLV_ERROR, LOCATION, NULL, ! 1130: "unable to alloc ldap init url\n"); ! 1131: goto ldap_group_end; ! 1132: } ! 1133: sprintf(init,"ldap://%s:%d", ! 1134: xauth_ldap_config.host->v, ! 1135: xauth_ldap_config.port ); ! 1136: ! 1137: /* initialize the ldap handle */ ! 1138: res = ldap_initialize(&ld, init); ! 1139: if (res != LDAP_SUCCESS) { ! 1140: plog(LLV_ERROR, LOCATION, NULL, ! 1141: "ldap_initialize failed: %s\n", ! 1142: ldap_err2string(res)); ! 1143: goto ldap_group_end; ! 1144: } ! 1145: ! 1146: /* initialize the protocol version */ ! 1147: ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, ! 1148: &xauth_ldap_config.pver); ! 1149: ! 1150: /* ! 1151: * attempt to bind to the ldap server. ! 1152: * default to anonymous bind unless a ! 1153: * user dn and password has been ! 1154: * specified in our configuration ! 1155: */ ! 1156: if ((xauth_ldap_config.bind_dn != NULL)&& ! 1157: (xauth_ldap_config.bind_pw != NULL)) ! 1158: { ! 1159: cred.bv_val = xauth_ldap_config.bind_pw->v; ! 1160: cred.bv_len = strlen( cred.bv_val ); ! 1161: res = ldap_sasl_bind_s(ld, ! 1162: xauth_ldap_config.bind_dn->v, NULL, &cred, ! 1163: NULL, NULL, NULL); ! 1164: } ! 1165: else ! 1166: { ! 1167: res = ldap_sasl_bind_s(ld, ! 1168: NULL, NULL, NULL, ! 1169: NULL, NULL, NULL); ! 1170: } ! 1171: ! 1172: if (res!=LDAP_SUCCESS) { ! 1173: plog(LLV_ERROR, LOCATION, NULL, ! 1174: "ldap_sasl_bind_s (search) failed: %s\n", ! 1175: ldap_err2string(res)); ! 1176: goto ldap_group_end; ! 1177: } ! 1178: ! 1179: /* build an ldap group search filter */ ! 1180: tmplen = strlen("(&(=)(=))") + 1; ! 1181: tmplen += strlen(xauth_ldap_config.attr_group->v); ! 1182: tmplen += strlen(grp); ! 1183: tmplen += strlen(xauth_ldap_config.attr_member->v); ! 1184: tmplen += strlen(udn); ! 1185: filter = racoon_malloc(tmplen); ! 1186: if (filter == NULL) { ! 1187: plog(LLV_ERROR, LOCATION, NULL, ! 1188: "unable to alloc ldap search filter buffer\n"); ! 1189: goto ldap_group_end; ! 1190: } ! 1191: sprintf(filter, "(&(%s=%s)(%s=%s))", ! 1192: xauth_ldap_config.attr_group->v, grp, ! 1193: xauth_ldap_config.attr_member->v, udn); ! 1194: ! 1195: /* attempt to locate the group dn */ ! 1196: if (xauth_ldap_config.base != NULL) ! 1197: basedn = xauth_ldap_config.base->v; ! 1198: if (xauth_ldap_config.subtree) ! 1199: scope = LDAP_SCOPE_SUBTREE; ! 1200: timeout.tv_sec = 15; ! 1201: timeout.tv_usec = 0; ! 1202: res = ldap_search_ext_s(ld, basedn, scope, ! 1203: filter, NULL, 0, NULL, NULL, ! 1204: &timeout, 2, &lr); ! 1205: if (res != LDAP_SUCCESS) { ! 1206: plog(LLV_ERROR, LOCATION, NULL, ! 1207: "ldap_search_ext_s failed: %s\n", ! 1208: ldap_err2string(res)); ! 1209: goto ldap_group_end; ! 1210: } ! 1211: ! 1212: /* check the number of ldap entries returned */ ! 1213: ecount = ldap_count_entries(ld, lr); ! 1214: if (ecount < 1) { ! 1215: plog(LLV_WARNING, LOCATION, NULL, ! 1216: "no ldap results for filter \'%s\'\n", ! 1217: filter); ! 1218: goto ldap_group_end; ! 1219: } ! 1220: ! 1221: /* success */ ! 1222: rtn = 0; ! 1223: ! 1224: /* obtain the dn from the first result */ ! 1225: le = ldap_first_entry(ld, lr); ! 1226: if (le == NULL) { ! 1227: plog(LLV_ERROR, LOCATION, NULL, ! 1228: "ldap_first_entry failed: invalid entry returned\n"); ! 1229: goto ldap_group_end; ! 1230: } ! 1231: groupdn = ldap_get_dn(ld, le); ! 1232: if (groupdn == NULL) { ! 1233: plog(LLV_ERROR, LOCATION, NULL, ! 1234: "ldap_get_dn failed: invalid string returned\n"); ! 1235: goto ldap_group_end; ! 1236: } ! 1237: ! 1238: plog(LLV_INFO, LOCATION, NULL, ! 1239: "ldap membership group returned \'%s\'\n", groupdn); ! 1240: ldap_group_end: ! 1241: ! 1242: /* free ldap resources */ ! 1243: if (groupdn != NULL) ! 1244: ldap_memfree(groupdn); ! 1245: if (filter != NULL) ! 1246: racoon_free(filter); ! 1247: if (lr != NULL) ! 1248: ldap_msgfree(lr); ! 1249: if (init != NULL) ! 1250: racoon_free(init); ! 1251: ! 1252: ldap_unbind_ext_s(ld, NULL, NULL); ! 1253: ! 1254: return rtn; ! 1255: } ! 1256: ! 1257: #endif ! 1258: ! 1259: int ! 1260: xauth_login_system(usr, pwd) ! 1261: char *usr; ! 1262: char *pwd; ! 1263: { ! 1264: struct passwd *pw; ! 1265: char *cryptpwd; ! 1266: char *syscryptpwd; ! 1267: #ifdef HAVE_SHADOW_H ! 1268: struct spwd *spw; ! 1269: ! 1270: if ((spw = getspnam(usr)) == NULL) ! 1271: return -1; ! 1272: ! 1273: syscryptpwd = spw->sp_pwdp; ! 1274: #endif ! 1275: ! 1276: if ((pw = getpwnam(usr)) == NULL) ! 1277: return -1; ! 1278: ! 1279: #ifndef HAVE_SHADOW_H ! 1280: syscryptpwd = pw->pw_passwd; ! 1281: #endif ! 1282: ! 1283: /* No root login. Ever. */ ! 1284: if (pw->pw_uid == 0) ! 1285: return -1; ! 1286: ! 1287: if ((cryptpwd = crypt(pwd, syscryptpwd)) == NULL) ! 1288: return -1; ! 1289: ! 1290: if (strcmp(cryptpwd, syscryptpwd) == 0) ! 1291: return 0; ! 1292: ! 1293: return -1; ! 1294: } ! 1295: ! 1296: int ! 1297: xauth_group_system(usr, grp) ! 1298: char * usr; ! 1299: char * grp; ! 1300: { ! 1301: struct group * gr; ! 1302: char * member; ! 1303: int index = 0; ! 1304: ! 1305: gr = getgrnam(grp); ! 1306: if (gr == NULL) { ! 1307: plog(LLV_ERROR, LOCATION, NULL, ! 1308: "the system group name \'%s\' is unknown\n", ! 1309: grp); ! 1310: return -1; ! 1311: } ! 1312: ! 1313: while ((member = gr->gr_mem[index++])!=NULL) { ! 1314: if (!strcmp(member,usr)) { ! 1315: plog(LLV_INFO, LOCATION, NULL, ! 1316: "membership validated\n"); ! 1317: return 0; ! 1318: } ! 1319: } ! 1320: ! 1321: return -1; ! 1322: } ! 1323: ! 1324: int ! 1325: xauth_check(iph1) ! 1326: struct ph1handle *iph1; ! 1327: { ! 1328: struct xauth_state *xst = &iph1->mode_cfg->xauth; ! 1329: ! 1330: /* ! 1331: * Only the server side (edge device) really check for Xauth ! 1332: * status. It does it if the chose authmethod is using Xauth. ! 1333: * On the client side (roadwarrior), we don't check anything. ! 1334: */ ! 1335: switch (iph1->approval->authmethod) { ! 1336: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: ! 1337: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: ! 1338: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: ! 1339: /* The following are not yet implemented */ ! 1340: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: ! 1341: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: ! 1342: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: ! 1343: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: ! 1344: if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { ! 1345: plog(LLV_ERROR, LOCATION, NULL, ! 1346: "Hybrid auth negotiated but peer did not " ! 1347: "announced as Xauth capable\n"); ! 1348: return -1; ! 1349: } ! 1350: ! 1351: if (xst->status != XAUTHST_OK) { ! 1352: plog(LLV_ERROR, LOCATION, NULL, ! 1353: "Hybrid auth negotiated but peer did not " ! 1354: "succeed Xauth exchange\n"); ! 1355: return -1; ! 1356: } ! 1357: ! 1358: return 0; ! 1359: break; ! 1360: default: ! 1361: return 0; ! 1362: break; ! 1363: } ! 1364: ! 1365: return 0; ! 1366: } ! 1367: ! 1368: int ! 1369: group_check(iph1, grp_list, grp_count) ! 1370: struct ph1handle *iph1; ! 1371: char **grp_list; ! 1372: int grp_count; ! 1373: { ! 1374: int res = -1; ! 1375: int grp_index = 0; ! 1376: char * usr = NULL; ! 1377: ! 1378: /* check for presence of modecfg data */ ! 1379: ! 1380: if(iph1->mode_cfg == NULL) { ! 1381: plog(LLV_ERROR, LOCATION, NULL, ! 1382: "xauth group specified but modecfg not found\n"); ! 1383: return res; ! 1384: } ! 1385: ! 1386: /* loop through our group list */ ! 1387: ! 1388: for(; grp_index < grp_count; grp_index++) { ! 1389: ! 1390: /* check for presence of xauth data */ ! 1391: ! 1392: usr = iph1->mode_cfg->xauth.authdata.generic.usr; ! 1393: ! 1394: if(usr == NULL) { ! 1395: plog(LLV_ERROR, LOCATION, NULL, ! 1396: "xauth group specified but xauth not found\n"); ! 1397: return res; ! 1398: } ! 1399: ! 1400: /* call appropriate group validation funtion */ ! 1401: ! 1402: switch (isakmp_cfg_config.groupsource) { ! 1403: ! 1404: case ISAKMP_CFG_GROUP_SYSTEM: ! 1405: res = xauth_group_system( ! 1406: usr, ! 1407: grp_list[grp_index]); ! 1408: break; ! 1409: ! 1410: #ifdef HAVE_LIBLDAP ! 1411: case ISAKMP_CFG_GROUP_LDAP: ! 1412: res = xauth_group_ldap( ! 1413: iph1->mode_cfg->xauth.udn, ! 1414: grp_list[grp_index]); ! 1415: break; ! 1416: #endif ! 1417: ! 1418: default: ! 1419: /* we should never get here */ ! 1420: plog(LLV_ERROR, LOCATION, NULL, ! 1421: "Unknown group auth source\n"); ! 1422: break; ! 1423: } ! 1424: ! 1425: if( !res ) { ! 1426: plog(LLV_INFO, LOCATION, NULL, ! 1427: "user \"%s\" is a member of group \"%s\"\n", ! 1428: usr, ! 1429: grp_list[grp_index]); ! 1430: break; ! 1431: } else { ! 1432: plog(LLV_INFO, LOCATION, NULL, ! 1433: "user \"%s\" is not a member of group \"%s\"\n", ! 1434: usr, ! 1435: grp_list[grp_index]); ! 1436: } ! 1437: } ! 1438: ! 1439: return res; ! 1440: } ! 1441: ! 1442: vchar_t * ! 1443: isakmp_xauth_req(iph1, attr) ! 1444: struct ph1handle *iph1; ! 1445: struct isakmp_data *attr; ! 1446: { ! 1447: int type; ! 1448: size_t dlen = 0; ! 1449: int ashort = 0; ! 1450: int value = 0; ! 1451: vchar_t *buffer = NULL; ! 1452: char *mraw = NULL, *mdata; ! 1453: char *data; ! 1454: vchar_t *usr = NULL; ! 1455: vchar_t *pwd = NULL; ! 1456: size_t skip = 0; ! 1457: int freepwd = 0; ! 1458: ! 1459: if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { ! 1460: plog(LLV_ERROR, LOCATION, NULL, ! 1461: "Xauth mode config request but peer " ! 1462: "did not declare itself as Xauth capable\n"); ! 1463: return NULL; ! 1464: } ! 1465: ! 1466: type = ntohs(attr->type) & ~ISAKMP_GEN_MASK; ! 1467: ! 1468: /* Sanity checks */ ! 1469: switch(type) { ! 1470: case XAUTH_TYPE: ! 1471: if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) { ! 1472: plog(LLV_ERROR, LOCATION, NULL, ! 1473: "Unexpected long XAUTH_TYPE attribute\n"); ! 1474: return NULL; ! 1475: } ! 1476: if (ntohs(attr->lorv) != XAUTH_TYPE_GENERIC) { ! 1477: plog(LLV_ERROR, LOCATION, NULL, ! 1478: "Unsupported Xauth authentication %d\n", ! 1479: ntohs(attr->lorv)); ! 1480: return NULL; ! 1481: } ! 1482: ashort = 1; ! 1483: dlen = 0; ! 1484: value = XAUTH_TYPE_GENERIC; ! 1485: break; ! 1486: ! 1487: case XAUTH_USER_NAME: ! 1488: if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login) { ! 1489: plog(LLV_ERROR, LOCATION, NULL, "Xauth performed " ! 1490: "with no login supplied\n"); ! 1491: return NULL; ! 1492: } ! 1493: ! 1494: dlen = iph1->rmconf->xauth->login->l - 1; ! 1495: iph1->rmconf->xauth->state |= XAUTH_SENT_USERNAME; ! 1496: break; ! 1497: ! 1498: case XAUTH_USER_PASSWORD: ! 1499: if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login) ! 1500: return NULL; ! 1501: ! 1502: skip = sizeof(struct ipsecdoi_id_b); ! 1503: usr = vmalloc(iph1->rmconf->xauth->login->l - 1 + skip); ! 1504: if (usr == NULL) { ! 1505: plog(LLV_ERROR, LOCATION, NULL, ! 1506: "Cannot allocate memory\n"); ! 1507: return NULL; ! 1508: } ! 1509: memset(usr->v, 0, skip); ! 1510: memcpy(usr->v + skip, ! 1511: iph1->rmconf->xauth->login->v, ! 1512: iph1->rmconf->xauth->login->l - 1); ! 1513: ! 1514: if (iph1->rmconf->xauth->pass) { ! 1515: /* A key given through racoonctl */ ! 1516: pwd = iph1->rmconf->xauth->pass; ! 1517: } else { ! 1518: if ((pwd = getpskbyname(usr)) == NULL) { ! 1519: plog(LLV_ERROR, LOCATION, NULL, ! 1520: "No password was found for login %s\n", ! 1521: iph1->rmconf->xauth->login->v); ! 1522: vfree(usr); ! 1523: return NULL; ! 1524: } ! 1525: /* We have to free it before returning */ ! 1526: freepwd = 1; ! 1527: } ! 1528: vfree(usr); ! 1529: ! 1530: iph1->rmconf->xauth->state |= XAUTH_SENT_PASSWORD; ! 1531: dlen = pwd->l; ! 1532: ! 1533: break; ! 1534: case XAUTH_MESSAGE: ! 1535: if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) { ! 1536: dlen = ntohs(attr->lorv); ! 1537: if (dlen > 0) { ! 1538: mraw = (char*)(attr + 1); ! 1539: mdata = binsanitize(mraw, dlen); ! 1540: if (mdata == NULL) { ! 1541: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1542: "Cannot allocate memory\n"); ! 1543: return NULL; ! 1544: } ! 1545: plog(LLV_NOTIFY,LOCATION, iph1->remote, ! 1546: "XAUTH Message: '%s'.\n", ! 1547: mdata); ! 1548: racoon_free(mdata); ! 1549: } ! 1550: } ! 1551: return NULL; ! 1552: default: ! 1553: plog(LLV_WARNING, LOCATION, NULL, ! 1554: "Ignored attribute %s\n", s_isakmp_cfg_type(type)); ! 1555: return NULL; ! 1556: break; ! 1557: } ! 1558: ! 1559: if ((buffer = vmalloc(sizeof(*attr) + dlen)) == NULL) { ! 1560: plog(LLV_ERROR, LOCATION, NULL, ! 1561: "Cannot allocate memory\n"); ! 1562: goto out; ! 1563: } ! 1564: ! 1565: attr = (struct isakmp_data *)buffer->v; ! 1566: if (ashort) { ! 1567: attr->type = htons(type | ISAKMP_GEN_TV); ! 1568: attr->lorv = htons(value); ! 1569: goto out; ! 1570: } ! 1571: ! 1572: attr->type = htons(type | ISAKMP_GEN_TLV); ! 1573: attr->lorv = htons(dlen); ! 1574: data = (char *)(attr + 1); ! 1575: ! 1576: switch(type) { ! 1577: case XAUTH_USER_NAME: ! 1578: /* ! 1579: * iph1->rmconf->xauth->login->v is valid, ! 1580: * we just checked it in the previous switch case ! 1581: */ ! 1582: memcpy(data, iph1->rmconf->xauth->login->v, dlen); ! 1583: break; ! 1584: case XAUTH_USER_PASSWORD: ! 1585: memcpy(data, pwd->v, dlen); ! 1586: break; ! 1587: default: ! 1588: break; ! 1589: } ! 1590: ! 1591: out: ! 1592: if (freepwd) ! 1593: vfree(pwd); ! 1594: ! 1595: return buffer; ! 1596: } ! 1597: ! 1598: vchar_t * ! 1599: isakmp_xauth_set(iph1, attr) ! 1600: struct ph1handle *iph1; ! 1601: struct isakmp_data *attr; ! 1602: { ! 1603: int type; ! 1604: vchar_t *buffer = NULL; ! 1605: char *data; ! 1606: struct xauth_state *xst; ! 1607: size_t dlen = 0; ! 1608: char* mraw = NULL, *mdata; ! 1609: ! 1610: if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { ! 1611: plog(LLV_ERROR, LOCATION, NULL, ! 1612: "Xauth mode config set but peer " ! 1613: "did not declare itself as Xauth capable\n"); ! 1614: return NULL; ! 1615: } ! 1616: ! 1617: type = ntohs(attr->type) & ~ISAKMP_GEN_MASK; ! 1618: ! 1619: switch(type) { ! 1620: case XAUTH_STATUS: ! 1621: /* ! 1622: * We should only receive ISAKMP mode_cfg SET XAUTH_STATUS ! 1623: * when running as a client (initiator). ! 1624: */ ! 1625: xst = &iph1->mode_cfg->xauth; ! 1626: switch (iph1->approval->authmethod) { ! 1627: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: ! 1628: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I: ! 1629: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: ! 1630: /* Not implemented ... */ ! 1631: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: ! 1632: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: ! 1633: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: ! 1634: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: ! 1635: break; ! 1636: default: ! 1637: plog(LLV_ERROR, LOCATION, NULL, ! 1638: "Unexpected XAUTH_STATUS_OK\n"); ! 1639: return NULL; ! 1640: break; ! 1641: } ! 1642: ! 1643: /* If we got a failure, delete iph1 */ ! 1644: if (ntohs(attr->lorv) != XAUTH_STATUS_OK) { ! 1645: plog(LLV_ERROR, LOCATION, NULL, ! 1646: "Xauth authentication failed\n"); ! 1647: ! 1648: evt_phase1(iph1, EVT_PHASE1_XAUTH_FAILED, NULL); ! 1649: ! 1650: iph1->mode_cfg->flags |= ISAKMP_CFG_DELETE_PH1; ! 1651: } else { ! 1652: evt_phase1(iph1, EVT_PHASE1_XAUTH_SUCCESS, NULL); ! 1653: } ! 1654: ! 1655: ! 1656: /* We acknowledge it */ ! 1657: break; ! 1658: case XAUTH_MESSAGE: ! 1659: if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) { ! 1660: dlen = ntohs(attr->lorv); ! 1661: if (dlen > 0) { ! 1662: mraw = (char*)(attr + 1); ! 1663: mdata = binsanitize(mraw, dlen); ! 1664: if (mdata == NULL) { ! 1665: plog(LLV_ERROR, LOCATION, iph1->remote, ! 1666: "Cannot allocate memory\n"); ! 1667: return NULL; ! 1668: } ! 1669: plog(LLV_NOTIFY,LOCATION, iph1->remote, ! 1670: "XAUTH Message: '%s'.\n", ! 1671: mdata); ! 1672: racoon_free(mdata); ! 1673: } ! 1674: } ! 1675: ! 1676: default: ! 1677: plog(LLV_WARNING, LOCATION, NULL, ! 1678: "Ignored attribute %s\n", s_isakmp_cfg_type(type)); ! 1679: return NULL; ! 1680: break; ! 1681: } ! 1682: ! 1683: if ((buffer = vmalloc(sizeof(*attr))) == NULL) { ! 1684: plog(LLV_ERROR, LOCATION, NULL, ! 1685: "Cannot allocate memory\n"); ! 1686: return NULL; ! 1687: } ! 1688: ! 1689: attr = (struct isakmp_data *)buffer->v; ! 1690: attr->type = htons(type | ISAKMP_GEN_TV); ! 1691: attr->lorv = htons(0); ! 1692: ! 1693: return buffer; ! 1694: } ! 1695: ! 1696: ! 1697: void ! 1698: xauth_rmstate(xst) ! 1699: struct xauth_state *xst; ! 1700: { ! 1701: switch (xst->authtype) { ! 1702: case XAUTH_TYPE_GENERIC: ! 1703: if (xst->authdata.generic.usr) ! 1704: racoon_free(xst->authdata.generic.usr); ! 1705: ! 1706: if (xst->authdata.generic.pwd) ! 1707: racoon_free(xst->authdata.generic.pwd); ! 1708: ! 1709: break; ! 1710: ! 1711: case XAUTH_TYPE_CHAP: ! 1712: case XAUTH_TYPE_OTP: ! 1713: case XAUTH_TYPE_SKEY: ! 1714: plog(LLV_WARNING, LOCATION, NULL, ! 1715: "Unsupported authtype %d\n", xst->authtype); ! 1716: break; ! 1717: ! 1718: default: ! 1719: plog(LLV_WARNING, LOCATION, NULL, ! 1720: "Unexpected authtype %d\n", xst->authtype); ! 1721: break; ! 1722: } ! 1723: ! 1724: #ifdef HAVE_LIBLDAP ! 1725: if (xst->udn != NULL) ! 1726: racoon_free(xst->udn); ! 1727: #endif ! 1728: return; ! 1729: } ! 1730: ! 1731: int ! 1732: xauth_rmconf_used(xauth_rmconf) ! 1733: struct xauth_rmconf **xauth_rmconf; ! 1734: { ! 1735: if (*xauth_rmconf == NULL) { ! 1736: *xauth_rmconf = racoon_malloc(sizeof(**xauth_rmconf)); ! 1737: if (*xauth_rmconf == NULL) { ! 1738: plog(LLV_ERROR, LOCATION, NULL, ! 1739: "xauth_rmconf_used: malloc failed\n"); ! 1740: return -1; ! 1741: } ! 1742: ! 1743: (*xauth_rmconf)->login = NULL; ! 1744: (*xauth_rmconf)->pass = NULL; ! 1745: (*xauth_rmconf)->state = 0; ! 1746: } ! 1747: ! 1748: return 0; ! 1749: } ! 1750: ! 1751: void ! 1752: xauth_rmconf_delete(xauth_rmconf) ! 1753: struct xauth_rmconf **xauth_rmconf; ! 1754: { ! 1755: if (*xauth_rmconf != NULL) { ! 1756: if ((*xauth_rmconf)->login != NULL) ! 1757: vfree((*xauth_rmconf)->login); ! 1758: if ((*xauth_rmconf)->pass != NULL) ! 1759: vfree((*xauth_rmconf)->pass); ! 1760: ! 1761: racoon_free(*xauth_rmconf); ! 1762: *xauth_rmconf = NULL; ! 1763: } ! 1764: ! 1765: return; ! 1766: } ! 1767: ! 1768: struct xauth_rmconf * ! 1769: xauth_rmconf_dup(xauth_rmconf) ! 1770: struct xauth_rmconf *xauth_rmconf; ! 1771: { ! 1772: struct xauth_rmconf *new; ! 1773: ! 1774: if (xauth_rmconf != NULL) { ! 1775: new = racoon_malloc(sizeof(*new)); ! 1776: if (new == NULL) { ! 1777: plog(LLV_ERROR, LOCATION, NULL, ! 1778: "xauth_rmconf_dup: malloc failed\n"); ! 1779: return NULL; ! 1780: } ! 1781: ! 1782: memcpy(new, xauth_rmconf, sizeof(*new)); ! 1783: ! 1784: if (xauth_rmconf->login != NULL) { ! 1785: new->login = vdup(xauth_rmconf->login); ! 1786: if (new->login == NULL) { ! 1787: plog(LLV_ERROR, LOCATION, NULL, ! 1788: "xauth_rmconf_dup: malloc failed (login)\n"); ! 1789: return NULL; ! 1790: } ! 1791: } ! 1792: if (xauth_rmconf->pass != NULL) { ! 1793: new->pass = vdup(xauth_rmconf->pass); ! 1794: if (new->pass == NULL) { ! 1795: plog(LLV_ERROR, LOCATION, NULL, ! 1796: "xauth_rmconf_dup: malloc failed (password)\n"); ! 1797: return NULL; ! 1798: } ! 1799: } ! 1800: ! 1801: return new; ! 1802: } ! 1803: ! 1804: return NULL; ! 1805: }