xref: /openbsd/usr.sbin/npppd/npppd/npppd_auth.c (revision ad8a6471)
1 /*	$OpenBSD: npppd_auth.c,v 1.23 2024/02/26 10:42:05 yasuoka 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.23 2024/02/26 10:42:05 yasuoka 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 "npppd_local.h"
48 #include "npppd_auth.h"
49 #include "net_utils.h"
50 
51 #include "npppd_auth_local.h"
52 #include "npppd_radius.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  */
67 npppd_auth_base *
npppd_auth_create(int auth_type,const char * name,void * _npppd)68 npppd_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 = calloc(1, sizeof(npppd_auth_local))) != NULL) {
77 			base->type = NPPPD_AUTH_TYPE_LOCAL;
78 			strlcpy(base->name, name, sizeof(base->name));
79 			base->npppd = _npppd;
80 
81 			return base;
82 		}
83 		break;
84 
85 #ifdef USE_NPPPD_RADIUS
86 	case NPPPD_AUTH_TYPE_RADIUS:
87 		if ((base = calloc(1, sizeof(npppd_auth_radius))) != NULL) {
88 			npppd_auth_radius *_this = (npppd_auth_radius *)base;
89 			base->type = NPPPD_AUTH_TYPE_RADIUS;
90 			strlcpy(base->name, name, sizeof(base->name));
91 			base->npppd = _npppd;
92 			if ((_this->rad_auth_setting =
93 			    radius_req_setting_create()) == NULL)
94 				goto radius_fail;
95 			if ((_this->rad_acct_setting =
96 			    radius_req_setting_create()) == NULL)
97 				goto radius_fail;
98 
99 			return base;
100 radius_fail:
101 			if (_this->rad_auth_setting != NULL)
102 				radius_req_setting_destroy(
103 				    _this->rad_auth_setting);
104 			if (_this->rad_acct_setting != NULL)
105 				radius_req_setting_destroy(
106 				    _this->rad_acct_setting);
107 			free(base);
108 			return NULL;
109 		}
110 
111 		break;
112 #endif
113 
114 	default:
115 		NPPPD_AUTH_ASSERT(0);
116 		break;
117 	}
118 
119 	return NULL;
120 }
121 
122 /**
123  * Call this function to make the object unusable.
124  * <p>
125  * {@link ::npppd_auth_base} objects is referred by the {@link ::npppd_ppp}
126  * object.   After this function is called, npppd will disconnect the PPP
127  * links that refers the object, it will call {@link ::npppd_auth_destroy()}
128  * when all the references to the object are released.</p>
129  */
130 void
npppd_auth_dispose(npppd_auth_base * base)131 npppd_auth_dispose(npppd_auth_base *base)
132 {
133 
134 	base->disposing = 1;
135 
136 	return;
137 }
138 
139 /** Destroy the {@link ::npppd_auth_base} object.  */
140 void
npppd_auth_destroy(npppd_auth_base * base)141 npppd_auth_destroy(npppd_auth_base *base)
142 {
143 
144 	if (base->disposing == 0)
145 		npppd_auth_dispose(base);
146 
147 	npppd_auth_base_log(base, LOG_INFO, "Finalized");
148 
149 	switch(base->type) {
150 	case NPPPD_AUTH_TYPE_LOCAL:
151 		memset(base, 0, sizeof(npppd_auth_local));
152 		break;
153 
154 #ifdef USE_NPPPD_RADIUS
155 	case NPPPD_AUTH_TYPE_RADIUS:
156 	    {
157 		npppd_auth_radius *_this = (npppd_auth_radius *)base;
158 		if (_this->rad_auth_setting != NULL)
159 			radius_req_setting_destroy(_this->rad_auth_setting);
160 		_this->rad_auth_setting = NULL;
161 		if (_this->rad_acct_setting != NULL)
162 			radius_req_setting_destroy(_this->rad_acct_setting);
163 		_this->rad_acct_setting = NULL;
164 		memset(base, 0, sizeof(npppd_auth_local));
165 		break;
166 	    }
167 #endif
168 	}
169 	free(base);
170 
171 	return;
172 }
173 
174 /** Reload the configuration */
175 int
npppd_auth_reload(npppd_auth_base * base)176 npppd_auth_reload(npppd_auth_base *base)
177 {
178 	struct authconf *auth;
179 
180 	TAILQ_FOREACH(auth, &base->npppd->conf.authconfs, entry) {
181 		if (strcmp(auth->name, base->name) == 0)
182 			break;
183 	}
184 	if (auth == NULL)
185 		return 1;
186 
187 	base->pppsuffix[0] = '\0';
188 	if (auth->username_suffix != NULL)
189 		strlcpy(base->pppsuffix, auth->username_suffix,
190 		    sizeof(base->pppsuffix));
191 	base->eap_capable = auth->eap_capable;
192 	base->strip_nt_domain = auth->strip_nt_domain;
193 	base->strip_atmark_realm = auth->strip_atmark_realm;
194 	base->has_users_file = 0;
195 	base->radius_ready = 0;
196 	base->user_max_session = auth->user_max_session;
197 
198 	if (strlen(auth->users_file_path) > 0) {
199 		strlcpy(base->users_file_path, auth->users_file_path,
200 		    sizeof(base->users_file_path));
201 		base->has_users_file = 1;
202 	} else {
203 		if (base->type == NPPPD_AUTH_TYPE_LOCAL) {
204 			npppd_auth_base_log(base,
205 			    LOG_WARNING, "missing users_file property.");
206 			goto fail;
207 		}
208 	}
209 
210 	switch (base->type) {
211 #ifdef USE_NPPPD_RADIUS
212 	case NPPPD_AUTH_TYPE_RADIUS:
213 		if (npppd_auth_radius_reload(base, auth) != 0)
214 			goto fail;
215 		break;
216 #endif
217 	}
218 	base->initialized = 1;
219 
220 	return 0;
221 
222 fail:
223 	base->initialized = 0;
224 	base->has_users_file = 0;
225 	base->radius_ready = 0;
226 
227 	return 1;
228 }
229 
230 /**
231  * This function gets specified user's password. The value 0 is returned
232  * if the call succeeds.
233  *
234  * @param	username	username which gets the password
235  * @param	password	buffers which stores the password
236  *				Specify NULL if you want to known the length of
237  *				the password only.
238  * @param	lppassword	pointer which indicates the length of
239  *				the buffer which stores the password.
240  * @return A value 1 is returned if user is unknown. A value 2 is returned
241  *				if password buffer is sufficient. A negative value is
242  *				returned if other error occurred.
243  */
244 int
npppd_auth_get_user_password(npppd_auth_base * base,const char * username,char * password,int * plpassword)245 npppd_auth_get_user_password(npppd_auth_base *base,
246     const char *username, char *password, int *plpassword)
247 {
248 	int              retval, sz, lpassword;
249 	npppd_auth_user *user;
250 
251 	NPPPD_AUTH_ASSERT(base != NULL);
252 	NPPPD_AUTH_DBG((base, LOG_DEBUG, "%s(%s)", __func__, username));
253 
254 	user = NULL;
255 	retval = 0;
256 	if (base->has_users_file == 0) {
257 		retval = -1;
258 		goto out;
259 	}
260 	if ((user = npppd_auth_get_user(base, username)) == NULL) {
261 		retval = 1;
262 		goto out;
263 	}
264 	if (password == NULL && plpassword == NULL) {
265 		retval = 0;
266 		goto out;
267 	}
268 	if (plpassword == NULL) {
269 		retval = -1;
270 		goto out;
271 	}
272 	lpassword = strlen(user->password) + 1;
273 	sz = *plpassword;
274 	*plpassword = lpassword;
275 	if (password == NULL) {
276 		retval = 0;
277 		goto out;
278 	}
279 	if (sz < lpassword) {
280 		retval = 2;
281 		goto out;
282 	}
283 	strlcpy(password, user->password, sz);
284 out:
285 	free(user);
286 
287 	return retval;
288 }
289 
290 /**
291  * This function gets specified users' Framed-IP-{Address,Netmask}.
292  * The value 0 is returned if the call succeeds.
293  * <p>
294  * Because authentication database is updated at any time, the password is
295  * possible to be inconsistent if this function is not called immediately
296  * after authentication. So this function is called immediately after
297  * authentication. </p>
298  * @param	username	username which gets the password
299  * @param	ip4address	pointer which indicates struct in_addr which
300  *						stores the Framed-IP-Address
301  * @param	ip4netmask	pointer which indicates struct in_addr which
302  *						stores Framed-IP-Netmask
303  */
304 int
npppd_auth_get_framed_ip(npppd_auth_base * base,const char * username,struct in_addr * ip4address,struct in_addr * ip4netmask)305 npppd_auth_get_framed_ip(npppd_auth_base *base, const char *username,
306     struct in_addr *ip4address, struct in_addr *ip4netmask)
307 {
308 	npppd_auth_user *user;
309 
310 	NPPPD_AUTH_ASSERT(base != NULL);
311 	NPPPD_AUTH_DBG((base, LOG_DEBUG, "%s(%s)", __func__, username));
312 	if (base->has_users_file == 0)
313 		return -1;
314 
315 	if ((user = npppd_auth_get_user(base, username)) == NULL)
316 		return 1;
317 
318 	if (user->framed_ip_address.s_addr != 0) {
319 		*ip4address = user->framed_ip_address;
320 		if (ip4netmask != NULL)
321 			*ip4netmask = user->framed_ip_netmask;
322 
323 		free(user);
324 		return 0;
325 	}
326 	free(user);
327 
328 	return 1;
329 }
330 
331 /**
332  * Retribute "Calling-Number" attribute of the user from the realm.
333  *
334  * @param username	Username.
335  * @param number	Pointer to the space for the Calling-Number.  This
336  *	can be NULL in case retributing the Calling-Number only.
337  * @param plnumber	Pointer to the length of the space for the
338  *	Calling-Number.
339  * @return 0 if the Calling-Number attribute is successfully retributed.
340  *	1 if the user has no Calling-Number attribute.  return -1 if the realm
341  *	doesn't have user attributes or other errors.   return 2 if the space
342  *	is not enough.
343  */
344 int
npppd_auth_get_calling_number(npppd_auth_base * base,const char * username,char * number,int * plnumber)345 npppd_auth_get_calling_number(npppd_auth_base *base, const char *username,
346     char *number, int *plnumber)
347 {
348 	int              retval, lcallnum, sz;
349 	npppd_auth_user *user;
350 
351 	user = NULL;
352 	retval = 0;
353 	if (base->has_users_file == 0)
354 		return -1;
355 
356 	if ((user = npppd_auth_get_user(base, username)) == NULL)
357 		return 1;
358 
359 	if (number == NULL && plnumber == NULL) {
360 		retval = 0;
361 		goto out;
362 	}
363 	if (plnumber == NULL) {
364 		retval = -1;
365 		goto out;
366 	}
367 	lcallnum = strlen(user->calling_number) + 1;
368 	sz = *plnumber;
369 	*plnumber = lcallnum;
370 	if (sz < lcallnum) {
371 		retval = 2;
372 		goto out;
373 	}
374 	strlcpy(number, user->calling_number, sz);
375 
376 out:
377 	free(user);
378 
379 	return retval;
380 }
381 
382 int
npppd_auth_get_type(npppd_auth_base * base)383 npppd_auth_get_type(npppd_auth_base *base)
384 {
385 	return base->type;
386 }
387 
388 int
npppd_auth_is_usable(npppd_auth_base * base)389 npppd_auth_is_usable(npppd_auth_base *base)
390 {
391     	return (base->initialized != 0 && base->disposing == 0)? 1 : 0;
392 }
393 
394 int
npppd_auth_is_ready(npppd_auth_base * base)395 npppd_auth_is_ready(npppd_auth_base *base)
396 {
397 	if (!npppd_auth_is_usable(base))
398 		return 0;
399 
400 	switch(base->type) {
401 	case NPPPD_AUTH_TYPE_LOCAL:
402 		return (base->has_users_file)? 1 : 0;
403 		/* NOTREACHED */
404 
405 	case NPPPD_AUTH_TYPE_RADIUS:
406 		return (base->has_users_file != 0 ||
407 		    base->radius_ready != 0)? 1 : 0;
408 		/* NOTREACHED */
409 	}
410 	NPPPD_AUTH_ASSERT(0);
411 
412     	return 0;
413 }
414 
415 int
npppd_auth_is_disposing(npppd_auth_base * base)416 npppd_auth_is_disposing(npppd_auth_base *base)
417 {
418 	return (base->disposing != 0)? 1 : 0;
419 }
420 
421 int
npppd_auth_is_eap_capable(npppd_auth_base * base)422 npppd_auth_is_eap_capable(npppd_auth_base *base)
423 {
424 	return (base->eap_capable != 0)? 1 : 0;
425 }
426 
427 const char *
npppd_auth_get_name(npppd_auth_base * base)428 npppd_auth_get_name(npppd_auth_base *base)
429 {
430 	return base->name;
431 }
432 
433 const char *
npppd_auth_get_suffix(npppd_auth_base * base)434 npppd_auth_get_suffix(npppd_auth_base *base)
435 {
436 	return base->pppsuffix;
437 }
438 
439 const char *
npppd_auth_username_for_auth(npppd_auth_base * base,const char * username,char * username_buffer)440 npppd_auth_username_for_auth(npppd_auth_base *base, const char *username,
441     char *username_buffer)
442 {
443 	const char *u0;
444 	char *atmark, *u1;
445 
446 	u0 = NULL;
447 	if (base->strip_nt_domain != 0) {
448 		if ((u0 = strchr(username, '\\')) != NULL)
449 			u0++;
450 	}
451 	if (u0 == NULL)
452 		u0 = username;
453 	u1 = username_buffer;
454 	if (username_buffer != u0)
455 		memmove(username_buffer, u0, MINIMUM(strlen(u0) + 1,
456 		    MAX_USERNAME_LENGTH));
457 	if (base->strip_atmark_realm != 0) {
458 		if ((atmark = strrchr(u1, '@')) != NULL)
459 			*atmark = '\0';
460 	}
461 
462 	return username_buffer;
463 }
464 
465 int
npppd_auth_user_session_unlimited(npppd_auth_base * _this)466 npppd_auth_user_session_unlimited(npppd_auth_base *_this)
467 {
468 	return (_this->user_max_session == 0) ? 1 : 0;
469 }
470 
471 int
npppd_check_auth_user_max_session(npppd_auth_base * _this,int count)472 npppd_check_auth_user_max_session(npppd_auth_base *_this, int count)
473 {
474 	if (!npppd_auth_user_session_unlimited(_this) &&
475 	    _this->user_max_session <= count)
476 		return 1;
477 	else
478 		return 0;
479 }
480 
481 /***********************************************************************
482  * Account list related functions
483  ***********************************************************************/
484 static npppd_auth_user *
npppd_auth_get_user(npppd_auth_base * base,const char * username)485 npppd_auth_get_user(npppd_auth_base *base, const char *username)
486 {
487 	int              lsuffix, lusername;
488 	const char      *un;
489 	char             buf[MAX_USERNAME_LENGTH];
490 	npppd_auth_user *u;
491 
492 	un = username;
493 	lsuffix = strlen(base->pppsuffix);
494 	lusername = strlen(username);
495 	if (lsuffix > 0 && lusername > lsuffix &&
496 	    strcmp(username + lusername - lsuffix, base->pppsuffix) == 0 &&
497 	    lusername - lsuffix < sizeof(buf)) {
498 		memcpy(buf, username, lusername - lsuffix);
499 		buf[lusername - lsuffix] = '\0';
500 		un = buf;
501 	}
502 
503 	if (priv_get_user_info(base->users_file_path, un, &u) == 0)
504 		return u;
505 
506 	return NULL;
507 }
508 
509 #ifdef USE_NPPPD_RADIUS
510 /***********************************************************************
511  * RADIUS
512  ***********************************************************************/
513 /** reload the configuration of RADIUS authentication realm */
514 static int
npppd_auth_radius_reload(npppd_auth_base * base,struct authconf * auth)515 npppd_auth_radius_reload(npppd_auth_base *base, struct authconf *auth)
516 {
517 	npppd_auth_radius  *_this = (npppd_auth_radius *)base;
518 	radius_req_setting *rad;
519 	struct radserver   *server;
520 	int                 i, nauth, nacct;
521 
522 	_this->rad_auth_setting->timeout =
523 	    (auth->data.radius.auth.timeout == 0)
524 		    ? DEFAULT_RADIUS_TIMEOUT : auth->data.radius.auth.timeout;
525 	_this->rad_acct_setting->timeout =
526 	    (auth->data.radius.acct.timeout == 0)
527 		    ? DEFAULT_RADIUS_TIMEOUT : auth->data.radius.acct.timeout;
528 
529 
530 	_this->rad_auth_setting->max_tries =
531 	    (auth->data.radius.auth.max_tries == 0)
532 		    ? DEFAULT_RADIUS_MAX_TRIES : auth->data.radius.auth.max_tries;
533 	_this->rad_acct_setting->max_tries =
534 	    (auth->data.radius.acct.max_tries == 0)
535 		    ? DEFAULT_RADIUS_MAX_TRIES : auth->data.radius.acct.max_tries;
536 
537 	_this->rad_auth_setting->max_failovers =
538 	    (auth->data.radius.auth.max_failovers == 0)
539 		    ? DEFAULT_RADIUS_MAX_FAILOVERS
540 		    : auth->data.radius.auth.max_failovers;
541 	_this->rad_acct_setting->max_failovers =
542 	    (auth->data.radius.acct.max_failovers == 0)
543 		    ? DEFAULT_RADIUS_MAX_FAILOVERS
544 		    : auth->data.radius.acct.max_failovers;
545 
546 	_this->rad_acct_setting->curr_server =
547 	_this->rad_auth_setting->curr_server = 0;
548 
549 	/* load configs for authentication server */
550 	rad = _this->rad_auth_setting;
551 	for (i = 0; i < countof(rad->server); i++)
552 		memset(&rad->server[i], 0, sizeof(rad->server[0]));
553 	i = 0;
554 	TAILQ_FOREACH(server, &auth->data.radius.auth.servers, entry) {
555 		if (i >= countof(rad->server))
556 			break;
557 		memcpy(&rad->server[i].peer, &server->address,
558 		    server->address.ss_len);
559 		if (((struct sockaddr_in *)&rad->server[i].peer)->sin_port
560 		    == 0)
561 			((struct sockaddr_in *)&rad->server[i].peer)->sin_port
562 			    = htons(DEFAULT_RADIUS_AUTH_PORT);
563 		strlcpy(rad->server[i].secret, server->secret,
564 		    sizeof(rad->server[i].secret));
565 		rad->server[i].enabled = 1;
566 		i++;
567 	}
568 	nauth = i;
569 
570 	/* load configs for accounting server */
571 	rad = _this->rad_acct_setting;
572 	for (i = 0; i < countof(rad->server); i++)
573 		memset(&rad->server[i], 0, sizeof(rad->server[0]));
574 	i = 0;
575 	TAILQ_FOREACH(server, &auth->data.radius.acct.servers, entry) {
576 		if (i >= countof(rad->server))
577 			break;
578 		memcpy(&rad->server[i].peer, &server->address,
579 		    server->address.ss_len);
580 		if (((struct sockaddr_in *)&rad->server[i].peer)->sin_port
581 		    == 0)
582 			((struct sockaddr_in *)&rad->server[i].peer)->sin_port
583 			    = htons(DEFAULT_RADIUS_ACCT_PORT);
584 		strlcpy(rad->server[i].secret, server->secret,
585 		    sizeof(rad->server[i].secret));
586 		rad->server[i].enabled = 1;
587 		i++;
588 	}
589 	nacct = i;
590 
591 	for (i = 0; i < countof(_this->rad_auth_setting->server); i++) {
592 		if (_this->rad_auth_setting->server[i].enabled)
593 			base->radius_ready = 1;
594 	}
595 
596 	npppd_auth_base_log(&_this->nar_base, LOG_INFO,
597 	    "Loaded configuration.  %d authentication server%s, %d accounting "
598 	    "server%s.",
599 	    nauth, (nauth > 1)? "s" : "", nacct, (nacct > 1)? "s" : "");
600 
601 	if (nacct > 0 && _this->rad_acct_on == 0) {
602 		radius_acct_on(base->npppd, _this->rad_acct_setting);
603 		_this->rad_acct_on = 1;
604 	}
605 
606 	return 0;
607 }
608 
609 /**
610  * Get {@link ::radius_req_setting} for RADIUS authentication of specified
611  * {@link ::npppd_auth_base} object.
612  */
613 void *
npppd_auth_radius_get_radius_auth_setting(npppd_auth_radius * _this)614 npppd_auth_radius_get_radius_auth_setting(npppd_auth_radius *_this)
615 {
616 	return _this->rad_auth_setting;
617 }
618 
619 /**
620  * Get {@link ::radius_req_setting} for RADIUS accounting of specified
621  * {@link ::npppd_auth_base} object.
622  */
623 void *
npppd_auth_radius_get_radius_acct_setting(npppd_auth_radius * _this)624 npppd_auth_radius_get_radius_acct_setting(npppd_auth_radius *_this)
625 {
626 	return _this->rad_acct_setting;
627 }
628 
629 #endif
630 
631 /***********************************************************************
632  * Helper functions
633  ***********************************************************************/
634 /** Log it which starts the label based on this instance. */
635 static int
npppd_auth_base_log(npppd_auth_base * _this,int prio,const char * fmt,...)636 npppd_auth_base_log(npppd_auth_base *_this, int prio, const char *fmt, ...)
637 {
638 	int status;
639 	char logbuf[BUFSIZ];
640 	va_list ap;
641 
642 	NPPPD_AUTH_ASSERT(_this != NULL);
643 	va_start(ap, fmt);
644 	snprintf(logbuf, sizeof(logbuf), "realm name=%s %s",
645 	    _this->name, fmt);
646 	status = vlog_printf(prio, logbuf, ap);
647 	va_end(ap);
648 
649 	return status;
650 }
651