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