radius.c revision 1.1.1.4
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
31extern char *global_host;	/* from slapd */
32static LUTIL_PASSWD_CHK_FUNC chk_radius;
33static const struct berval scheme = BER_BVC("{RADIUS}");
34static char *config_filename;
35static ldap_pvt_thread_mutex_t libradius_mutex;
36
37static int
38chk_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
115done:;
116	rad_close( h );
117
118	ldap_pvt_thread_mutex_unlock( &libradius_mutex );
119	return rc;
120}
121
122int
123term_module()
124{
125	return ldap_pvt_thread_mutex_destroy( &libradius_mutex );
126}
127
128int
129init_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