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