xref: /netbsd-src/external/bsd/openldap/dist/contrib/slapd-modules/passwd/radius.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: radius.c,v 1.3 2021/08/14 16:14:52 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1998-2021 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 
18 #include <sys/cdefs.h>
19 __RCSID("$NetBSD: radius.c,v 1.3 2021/08/14 16:14:52 christos Exp $");
20 
21 #include "portable.h"
22 
23 #include <stdio.h>
24 
25 #include <lber.h>
26 #include <lber_pvt.h>	/* BER_BVC definition */
27 #include "lutil.h"
28 #include <ldap_pvt_thread.h>
29 #include <ac/string.h>
30 #include <ac/unistd.h>
31 
32 #include <radlib.h>
33 
34 extern char *global_host;	/* from slapd */
35 static LUTIL_PASSWD_CHK_FUNC chk_radius;
36 static const struct berval scheme = BER_BVC("{RADIUS}");
37 static char *config_filename;
38 static ldap_pvt_thread_mutex_t libradius_mutex;
39 
40 static int
chk_radius(const struct berval * sc,const struct berval * passwd,const struct berval * cred,const char ** text)41 chk_radius(
42 	const struct berval	*sc,
43 	const struct berval	*passwd,
44 	const struct berval	*cred,
45 	const char		**text )
46 {
47 	unsigned int		i;
48 	int			rc = LUTIL_PASSWD_ERR;
49 
50 	struct rad_handle	*h = NULL;
51 
52 	for ( i = 0; i < cred->bv_len; i++ ) {
53 		if ( cred->bv_val[ i ] == '\0' ) {
54 			return LUTIL_PASSWD_ERR;	/* NUL character in cred */
55 		}
56 	}
57 
58 	if ( cred->bv_val[ i ] != '\0' ) {
59 		return LUTIL_PASSWD_ERR;	/* cred must behave like a string */
60 	}
61 
62 	for ( i = 0; i < passwd->bv_len; i++ ) {
63 		if ( passwd->bv_val[ i ] == '\0' ) {
64 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
65 		}
66 	}
67 
68 	if ( passwd->bv_val[ i ] != '\0' ) {
69 		return LUTIL_PASSWD_ERR;	/* passwd must behave like a string */
70 	}
71 
72 	ldap_pvt_thread_mutex_lock( &libradius_mutex );
73 
74 	h = rad_auth_open();
75 	if ( h == NULL ) {
76 		ldap_pvt_thread_mutex_unlock( &libradius_mutex );
77 		return LUTIL_PASSWD_ERR;
78 	}
79 
80 	if ( rad_config( h, config_filename ) != 0 ) {
81 		goto done;
82 	}
83 
84 	if ( rad_create_request( h, RAD_ACCESS_REQUEST ) ) {
85 		goto done;
86 	}
87 
88 	if ( rad_put_string( h, RAD_USER_NAME, passwd->bv_val ) != 0 ) {
89 		goto done;
90 	}
91 
92 	if ( rad_put_string( h, RAD_USER_PASSWORD, cred->bv_val ) != 0 ) {
93 		goto done;
94 	}
95 
96 	if ( rad_put_string( h, RAD_NAS_IDENTIFIER, global_host ) != 0 ) {
97 		goto done;
98 	}
99 
100 	switch ( rad_send_request( h ) ) {
101 	case RAD_ACCESS_ACCEPT:
102 		rc = LUTIL_PASSWD_OK;
103 		break;
104 
105 	case RAD_ACCESS_REJECT:
106 		rc = LUTIL_PASSWD_ERR;
107 		break;
108 
109 	case RAD_ACCESS_CHALLENGE:
110 		rc = LUTIL_PASSWD_ERR;
111 		break;
112 
113 	case -1:
114 		/* no valid response is received */
115 		break;
116 	}
117 
118 done:;
119 	rad_close( h );
120 
121 	ldap_pvt_thread_mutex_unlock( &libradius_mutex );
122 	return rc;
123 }
124 
125 int
term_module()126 term_module()
127 {
128 	return ldap_pvt_thread_mutex_destroy( &libradius_mutex );
129 }
130 
131 int
init_module(int argc,char * argv[])132 init_module( int argc, char *argv[] )
133 {
134 	int	i;
135 
136 	for ( i = 0; i < argc; i++ ) {
137 		if ( strncasecmp( argv[ i ], "config=", STRLENOF( "config=" ) ) == 0 ) {
138 			/* FIXME: what if multiple loads of same module?
139 			 * does it make sense (e.g. override an existing one)? */
140 			if ( config_filename == NULL ) {
141 				config_filename = ber_strdup( &argv[ i ][ STRLENOF( "config=" ) ] );
142 			}
143 
144 		} else {
145 			fprintf( stderr, "init_module(radius): unknown arg#%d=\"%s\".\n",
146 				i, argv[ i ] );
147 			return 1;
148 		}
149 	}
150 
151 	ldap_pvt_thread_mutex_init( &libradius_mutex );
152 
153 	return lutil_passwd_add( (struct berval *)&scheme, chk_radius, NULL );
154 }
155