npppd_auth.c revision 1.11
1/* $OpenBSD: npppd_auth.c,v 1.11 2012/09/22 20:22:48 espie Exp $ */ 2 3/*- 4 * Copyright (c) 2009 Internet Initiative Japan Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28/**@file authentication realm */ 29/* $Id: npppd_auth.c,v 1.11 2012/09/22 20:22:48 espie Exp $ */ 30#include <sys/types.h> 31#include <sys/stat.h> 32#include <sys/socket.h> 33#include <netinet/in.h> 34#include <net/if_dl.h> 35#include <arpa/inet.h> 36#include <stdio.h> 37#include <syslog.h> 38#include <string.h> 39#include <time.h> 40#include <event.h> 41#include <stdarg.h> 42#include <stdlib.h> 43#include <netdb.h> 44#include <errno.h> 45 46#include "debugutil.h" 47#include "slist.h" 48#include "npppd_local.h" 49#include "npppd_auth.h" 50#include "net_utils.h" 51 52#include "npppd_auth_local.h" 53 54/** 55 * Create a npppd_auth_base object. 56 * @param auth_type the authentication type. 57 * specify {@link ::NPPPD_AUTH_TYPE_LOCAL} to authenticate by the local 58 * file, or specify {@link ::NPPPD_AUTH_TYPE_RADIUS} for RADIUS 59 * authentication. 60 * @param name the configuration name 61 * @param _npppd the parent {@link ::npppd} object 62 * @see ::NPPPD_AUTH_TYPE_LOCAL 63 * @see ::NPPPD_AUTH_TYPE_RADIUS 64 * @return The pointer to the {@link ::npppd_auth_base} object will be returned 65 * in case success otherwise NULL will be returned. 66 */ 67npppd_auth_base * 68npppd_auth_create(int auth_type, const char *name, void *_npppd) 69{ 70 npppd_auth_base *base; 71 72 NPPPD_AUTH_ASSERT(name != NULL); 73 74 switch (auth_type) { 75 case NPPPD_AUTH_TYPE_LOCAL: 76 if ((base = malloc(sizeof(npppd_auth_local))) != NULL) { 77 memset(base, 0, sizeof(npppd_auth_local)); 78 base->type = NPPPD_AUTH_TYPE_LOCAL; 79 base->strip_nt_domain = 1; 80 base->strip_atmark_realm = 0; 81 strlcpy(base->name, name, sizeof(base->name)); 82 base->npppd = _npppd; 83 84 return base; 85 } 86 break; 87 88#ifdef USE_NPPPD_RADIUS 89 case NPPPD_AUTH_TYPE_RADIUS: 90 if ((base = malloc(sizeof(npppd_auth_radius))) != NULL) { 91 npppd_auth_radius *_this = (npppd_auth_radius *)base; 92 memset(base, 0, sizeof(npppd_auth_radius)); 93 base->type = NPPPD_AUTH_TYPE_RADIUS; 94 base->strip_nt_domain = 0; 95 strlcpy(base->name, name, sizeof(base->name)); 96 base->npppd = _npppd; 97 if ((_this->rad_auth_setting = 98 radius_req_setting_create()) == NULL) 99 goto radius_fail; 100 if ((_this->rad_acct_setting = 101 radius_req_setting_create()) == NULL) 102 goto radius_fail; 103 104 return base; 105radius_fail: 106 if (_this->rad_auth_setting != NULL) 107 radius_req_setting_destroy( 108 _this->rad_auth_setting); 109 if (_this->rad_acct_setting != NULL) 110 radius_req_setting_destroy( 111 _this->rad_acct_setting); 112 free(base); 113 return NULL; 114 } 115 116 break; 117#endif 118 119 default: 120 NPPPD_AUTH_ASSERT(0); 121 break; 122 } 123 124 return NULL; 125} 126 127/** 128 * Call this function to make the object unusable. 129 * <p> 130 * {@link ::npppd_auth_base} objects is refered by the {@link ::npppd_ppp} 131 * object. After this funcation is called, npppd will disconnect the PPP 132 * links that refers the object, it will call {@link ::npppd_auth_destroy()} 133 * when all the references to the object are released.</p> 134 */ 135void 136npppd_auth_dispose(npppd_auth_base *base) 137{ 138 139 base->disposing = 1; 140 141 return; 142} 143 144/** Destroy the {@link ::npppd_auth_base} object. */ 145void 146npppd_auth_destroy(npppd_auth_base *base) 147{ 148 149 if (base->disposing == 0) 150 npppd_auth_dispose(base); 151 152 npppd_auth_base_log(base, LOG_INFO, "Finalized"); 153 154 switch(base->type) { 155 case NPPPD_AUTH_TYPE_LOCAL: 156 memset(base, 0, sizeof(npppd_auth_local)); 157 break; 158 159#ifdef USE_NPPPD_RADIUS 160 case NPPPD_AUTH_TYPE_RADIUS: 161 { 162 npppd_auth_radius *_this = (npppd_auth_radius *)base; 163 if (_this->rad_auth_setting != NULL) 164 radius_req_setting_destroy(_this->rad_auth_setting); 165 _this->rad_auth_setting = NULL; 166 if (_this->rad_acct_setting != NULL) 167 radius_req_setting_destroy(_this->rad_acct_setting); 168 _this->rad_acct_setting = NULL; 169 memset(base, 0, sizeof(npppd_auth_local)); 170 break; 171 } 172#endif 173 } 174 free(base); 175 176 return; 177} 178 179/** Reload the configuration */ 180int 181npppd_auth_reload(npppd_auth_base *base) 182{ 183 struct authconf *auth; 184 185 TAILQ_FOREACH(auth, &base->npppd->conf.authconfs, entry) { 186 if (strcmp(auth->name, base->name) == 0) 187 break; 188 } 189 if (auth == NULL) 190 return 1; 191 192 base->pppprefix[0] = '\0'; 193 base->pppsuffix[0] = '\0'; 194 if (auth != NULL) { 195 if (auth->username_suffix != NULL) 196 strlcpy(base->pppsuffix, auth->username_suffix, 197 sizeof(base->pppsuffix)); 198 if (auth->username_prefix != NULL) 199 strlcpy(base->pppprefix, auth->username_prefix, 200 sizeof(base->pppprefix)); 201 base->eap_capable = auth->eap_capable; 202 base->strip_nt_domain = auth->strip_nt_domain; 203 base->strip_atmark_realm = auth->strip_atmark_realm; 204 } 205 206 base->has_users_file = 0; 207 base->radius_ready = 0; 208 209 if (auth->users_file_path != NULL) { 210 strlcpy(base->users_file_path, auth->users_file_path, 211 sizeof(base->users_file_path)); 212 base->has_users_file = 1; 213 } else { 214 if (base->type == NPPPD_AUTH_TYPE_LOCAL) { 215 npppd_auth_base_log(base, 216 LOG_WARNING, "missing users_file property."); 217 goto fail; 218 } 219 } 220 221 switch (base->type) { 222#ifdef USE_NPPPD_RADIUS 223 case NPPPD_AUTH_TYPE_RADIUS: 224 if (npppd_auth_radius_reload(base, auth) != 0) 225 goto fail; 226 break; 227#endif 228 } 229 base->initialized = 1; 230 231 return 0; 232 233fail: 234 base->initialized = 0; 235 base->has_users_file = 0; 236 base->radius_ready = 0; 237 238 return 1; 239} 240 241/** 242 * This function gets specified user's password. The value 0 is returned 243 * if the call succeeds. 244 * 245 * @param username username which gets the password 246 * @param password buffers which stores the password 247 * Specify NULL if you want to known the length of 248 * the password only. 249 * @param lppassword pointer which indicates the length of 250 * the buffer which stores the password. 251 * @return A value 1 is returned if user is unknown. A value 2 is returned 252 * if password buffer is sufficient. A negative value is 253 * returned if other error occurred. 254 */ 255int 256npppd_auth_get_user_password(npppd_auth_base *base, 257 const char *username, char *password, int *plpassword) 258{ 259 int retval, sz, lpassword; 260 npppd_auth_user *user; 261 262 NPPPD_AUTH_ASSERT(base != NULL); 263 NPPPD_AUTH_DBG((base, LOG_DEBUG, "%s(%s)", __func__, username)); 264 265 user = NULL; 266 retval = 0; 267 if (base->has_users_file == 0) { 268 retval = -1; 269 goto out; 270 } 271 if ((user = npppd_auth_get_user(base, username)) == NULL) { 272 retval = 1; 273 goto out; 274 } 275 if (password == NULL && plpassword == NULL) { 276 retval = 0; 277 goto out; 278 } 279 if (plpassword == NULL) { 280 retval = -1; 281 goto out; 282 } 283 lpassword = strlen(user->password) + 1; 284 sz = *plpassword; 285 *plpassword = lpassword; 286 if (password == NULL) { 287 retval = 0; 288 goto out; 289 } 290 if (sz < lpassword) { 291 retval = 2; 292 goto out; 293 } 294 strlcpy(password, user->password, sz); 295out: 296 if (user != NULL) 297 free(user); 298 299 return retval; 300} 301 302/** 303 * This function gets specified users' Framed-IP-{Address,Netmask}. 304 * The value 0 is returned if the call succeeds. 305 * <p> 306 * Because authentication database is updated at any time, the password is 307 * possible to be inconsistent if this function is not called immediately 308 * after authentication. So this function is called immediately after 309 * authentication. </p> 310 * @param username username which gets the password 311 * @param ip4address pointer which indicates struct in_addr which 312 * stores the Framed-IP-Address 313 * @param ip4netmask pointer which indicates struct in_addr which 314 * stores Framed-IP-Netmask 315 */ 316int 317npppd_auth_get_framed_ip(npppd_auth_base *base, const char *username, 318 struct in_addr *ip4address, struct in_addr *ip4netmask) 319{ 320 npppd_auth_user *user; 321 322 NPPPD_AUTH_ASSERT(base != NULL); 323 NPPPD_AUTH_DBG((base, LOG_DEBUG, "%s(%s)", __func__, username)); 324 if (base->has_users_file == 0) 325 return -1; 326 327 if ((user = npppd_auth_get_user(base, username)) == NULL) 328 return 1; 329 330 if (user->framed_ip_address.s_addr != 0) { 331 *ip4address = user->framed_ip_address; 332 if (ip4netmask != NULL) 333 *ip4netmask = user->framed_ip_netmask; 334 335 free(user); 336 return 0; 337 } 338 free(user); 339 340 return 1; 341} 342 343/** 344 * Retribute "Calling-Number" attribute of the user from the realm. 345 * 346 * @param username Username. 347 * @param number Pointer to the space for the Calling-Number. This 348 * can be NULL in case retributing the Calling-Number only. 349 * @param plnumber Pointer to the length of the space for the 350 * Calling-Number. 351 * @return 0 if the Calling-Number attribute is successfully retributed. 352 * 1 if the user has no Calling-Number attribute. return -1 if the realm 353 * doesn't have user attributes or other errors. return 2 if the space 354 * is not enough. 355 */ 356int 357npppd_auth_get_calling_number(npppd_auth_base *base, const char *username, 358 char *number, int *plnumber) 359{ 360 int retval, lcallnum, sz; 361 npppd_auth_user *user; 362 363 user = NULL; 364 retval = 0; 365 if (base->has_users_file == 0) 366 return -1; 367 368 if ((user = npppd_auth_get_user(base, username)) == NULL) 369 return 1; 370 371 if (number == NULL && plnumber == NULL) { 372 retval = 0; 373 goto out; 374 } 375 if (plnumber == NULL) { 376 retval = -1; 377 goto out; 378 } 379 lcallnum = strlen(user->calling_number) + 1; 380 sz = *plnumber; 381 *plnumber = lcallnum; 382 if (sz < lcallnum) { 383 retval = 2; 384 goto out; 385 } 386 strlcpy(number, user->calling_number, sz); 387 388out: 389 if (user != NULL) 390 free(user); 391 392 return retval; 393} 394 395int 396npppd_auth_get_type(npppd_auth_base *base) 397{ 398 return base->type; 399} 400 401int 402npppd_auth_is_usable(npppd_auth_base *base) 403{ 404 return (base->initialized != 0 && base->disposing == 0)? 1 : 0; 405} 406 407int 408npppd_auth_is_ready(npppd_auth_base *base) 409{ 410 if (!npppd_auth_is_usable(base)) 411 return 0; 412 413 switch(base->type) { 414 case NPPPD_AUTH_TYPE_LOCAL: 415 return (base->has_users_file)? 1 : 0; 416 /* NOTREACHED */ 417 418 case NPPPD_AUTH_TYPE_RADIUS: 419 return (base->has_users_file != 0 || 420 base->radius_ready != 0)? 1 : 0; 421 /* NOTREACHED */ 422 } 423 NPPPD_AUTH_ASSERT(0); 424 425 return 0; 426} 427 428int 429npppd_auth_is_disposing(npppd_auth_base *base) 430{ 431 return (base->disposing != 0)? 1 : 0; 432} 433 434int 435npppd_auth_is_eap_capable(npppd_auth_base *base) 436{ 437 return (base->eap_capable != 0)? 1 : 0; 438} 439 440const char * 441npppd_auth_get_name(npppd_auth_base *base) 442{ 443 return base->name; 444} 445 446const char * 447npppd_auth_get_suffix(npppd_auth_base *base) 448{ 449 return base->pppsuffix; 450} 451 452const char * 453npppd_auth_get_prefix(npppd_auth_base *base) 454{ 455 return base->pppprefix; 456} 457 458const char * 459npppd_auth_username_for_auth(npppd_auth_base *base, const char *username, 460 char *username_buffer) 461{ 462 const char *u0; 463 char *atmark, *u1; 464 465 u0 = NULL; 466 if (base->strip_nt_domain != 0) { 467 if ((u0 = strchr(username, '\\')) != NULL) 468 u0++; 469 } 470 if (u0 == NULL) 471 u0 = username; 472 u1 = username_buffer; 473 if (username_buffer != u0) 474 memmove(username_buffer, u0, MIN(strlen(u0) + 1, 475 MAX_USERNAME_LENGTH)); 476 if (base->strip_atmark_realm != 0) { 477 if ((atmark = strrchr(u1, '@')) != NULL) 478 *atmark = '\0'; 479 } 480 481 return username_buffer; 482} 483 484/*********************************************************************** 485 * Account list related functions 486 ***********************************************************************/ 487static npppd_auth_user * 488npppd_auth_get_user(npppd_auth_base *base, const char *username) 489{ 490 int lsuffix, lusername; 491 const char *un; 492 char buf[MAX_USERNAME_LENGTH]; 493 npppd_auth_user *u; 494 495 un = username; 496 lsuffix = strlen(base->pppsuffix); 497 if (lsuffix > 0) { 498 /* Strip the suffix */ 499 lusername = strlen(username); 500 NPPPD_AUTH_ASSERT(lusername + 1 < sizeof(buf)); 501 if (lusername + 1 >= sizeof(buf)) 502 return NULL; 503 memcpy(buf, username, lusername - lsuffix); 504 buf[lusername - lsuffix] = '\0'; 505 un = buf; 506 } 507 508 if (priv_get_user_info(base->users_file_path, un, &u) == 0) 509 return u; 510 511 return NULL; 512} 513 514#ifdef USE_NPPPD_RADIUS 515/*********************************************************************** 516 * RADIUS 517 ***********************************************************************/ 518/** reload the configuration of RADIUS authentication realm */ 519static int 520npppd_auth_radius_reload(npppd_auth_base *base, struct authconf *auth) 521{ 522 npppd_auth_radius *_this = (npppd_auth_radius *)base; 523 radius_req_setting *rad; 524 struct radserver *server; 525 int i, nauth, nacct; 526 527 _this->rad_auth_setting->timeout = 528 (auth->data.radius.auth.timeout == 0) 529 ? DEFAULT_RADIUS_TIMEOUT : auth->data.radius.auth.timeout; 530 _this->rad_acct_setting->timeout = 531 (auth->data.radius.acct.timeout == 0) 532 ? DEFAULT_RADIUS_TIMEOUT : auth->data.radius.acct.timeout; 533 534 535 _this->rad_auth_setting->max_tries = 536 (auth->data.radius.auth.max_tries == 0) 537 ? DEFAULT_RADIUS_MAX_TRIES : auth->data.radius.auth.max_tries; 538 _this->rad_acct_setting->max_tries = 539 (auth->data.radius.acct.max_tries == 0) 540 ? DEFAULT_RADIUS_MAX_TRIES : auth->data.radius.acct.max_tries; 541 542 _this->rad_auth_setting->max_failovers = 543 (auth->data.radius.auth.max_failovers == 0) 544 ? DEFAULT_RADIUS_MAX_FAILOVERS 545 : auth->data.radius.auth.max_failovers; 546 _this->rad_acct_setting->max_failovers = 547 (auth->data.radius.acct.max_failovers == 0) 548 ? DEFAULT_RADIUS_MAX_FAILOVERS 549 : auth->data.radius.acct.max_failovers; 550 551 _this->rad_acct_setting->curr_server = 552 _this->rad_auth_setting->curr_server = 0; 553 554 /* load configs for authentication server */ 555 rad = _this->rad_auth_setting; 556 for (i = 0; i < countof(rad->server); i++) 557 memset(&rad->server[i], 0, sizeof(rad->server[0])); 558 i = 0; 559 TAILQ_FOREACH(server, &auth->data.radius.auth.servers, entry) { 560 if (i >= countof(rad->server)) 561 break; 562 memcpy(&rad->server[i].peer, &server->address, 563 server->address.ss_len); 564 strlcpy(rad->server[i].secret, server->secret, 565 sizeof(rad->server[i].secret)); 566 rad->server[i].enabled = 1; 567 i++; 568 } 569 nauth = i; 570 571 /* load configs for accounting server */ 572 rad = _this->rad_acct_setting; 573 for (i = 0; i < countof(rad->server); i++) 574 memset(&rad->server[i], 0, sizeof(rad->server[0])); 575 i = 0; 576 TAILQ_FOREACH(server, &auth->data.radius.acct.servers, entry) { 577 if (i >= countof(rad->server)) 578 break; 579 memcpy(&rad->server[i].peer, &server->address, 580 server->address.ss_len); 581 strlcpy(rad->server[i].secret, server->secret, 582 sizeof(rad->server[i].secret)); 583 rad->server[i].enabled = 1; 584 i++; 585 } 586 nacct = i; 587 588 for (i = 0; i < countof(_this->rad_auth_setting->server); i++) { 589 if (_this->rad_auth_setting->server[i].enabled) 590 base->radius_ready = 1; 591 } 592 593 npppd_auth_base_log(&_this->nar_base, LOG_INFO, 594 "Loaded configuration. %d authentication server%s, %d accounting " 595 "server%s.", 596 nauth, (nauth > 1)? "s" : "", nacct, (nacct > 1)? "s" : ""); 597 598 return 0; 599} 600 601/** 602 * Get {@link ::radius_req_setting} for RADIUS authentication of specified 603 * {@link ::npppd_auth_base} object. 604 */ 605void * 606npppd_auth_radius_get_radius_auth_setting(npppd_auth_radius *_this) 607{ 608 return _this->rad_auth_setting; 609} 610 611/** 612 * Get {@link ::radius_req_setting} for RADIUS accounting of specified 613 * {@link ::npppd_auth_base} object. 614 */ 615void * 616npppd_auth_radius_get_radius_acct_setting(npppd_auth_radius *_this) 617{ 618 return _this->rad_acct_setting; 619} 620 621#endif 622 623/*********************************************************************** 624 * Helper functions 625 ***********************************************************************/ 626/** Log it which starts the label based on this instance. */ 627static int 628npppd_auth_base_log(npppd_auth_base *_this, int prio, const char *fmt, ...) 629{ 630 int status; 631 char logbuf[BUFSIZ]; 632 va_list ap; 633 634 NPPPD_AUTH_ASSERT(_this != NULL); 635 va_start(ap, fmt); 636 snprintf(logbuf, sizeof(logbuf), "realm name=%s %s", 637 _this->name, fmt); 638 status = vlog_printf(prio, logbuf, ap); 639 va_end(ap); 640 641 return status; 642} 643