1/*
2 * $Id: radius.c,v 1.1.1.1 2008/10/15 03:30:40 james26_jang Exp $
3 *
4 * Copyright (C) 1996 Lars Fenneberg
5 *
6 * See the file COPYRIGHT for the respective terms and conditions.
7 * If the file is missing contact me at lf@elemental.net
8 * and I'll send you a copy.
9 *
10 */
11
12#include <config.h>
13#include <includes.h>
14#include <radiusclient.h>
15#include <messages.h>
16#include <radlogin.h>
17
18extern ENV *env;
19
20LFUNC auth_radius(UINT4 client_port, char *username, char *passwd)
21{
22
23	VALUE_PAIR	*send, *received, *vp, *service_vp;
24	UINT4		service, ftype, ctype;
25	char		msg[4096], *p, username_realm[256];
26	char            name[2048], value[2048]; /* more than enough */
27	int		result;
28	char		*default_realm, *service_str, *ftype_str;
29	DICT_VALUE	*dval;
30
31	send = received = NULL;
32
33	/*
34	 * Determine and fill in Service-Type
35	 */
36
37#ifdef SCP
38	/* determine based on the username what kind of service is requested.
39	   this allows you to use one password for all accounts, but the
40	   Merit radiusd supplies you just with the right information you
41	   need for the specified service type	-lf, 03/15/96 */
42
43	switch (*username)
44	{
45		case 'S':
46				service = PW_FRAMED;
47				ftype = PW_SLIP;
48				ctype = 0;
49				username++;
50				break;
51		case 'C':
52				service = PW_FRAMED;
53				ftype = PW_SLIP;
54				ctype = PW_VAN_JACOBSON_TCP_IP;
55				username++;
56				break;
57		case 'P':
58				service = PW_FRAMED;
59				ftype = PW_PPP;
60				ctype = 0;
61				username++;
62				break;
63		default:
64				service = PW_LOGIN;
65				ftype = 0;
66				ctype = 0;
67				break;
68	}
69#else
70	service = PW_LOGIN;
71	ftype = 0;
72	ctype = 0;
73#endif
74
75	if (rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0, VENDOR_NONE) == NULL)
76		return (LFUNC) NULL;
77
78	/* Fill in Framed-Protocol, if neccessary */
79
80	if (ftype != 0)
81	{
82		if (rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &ftype, 0, VENDOR_NONE) == NULL)
83			return (LFUNC) NULL;
84	}
85
86	/* Fill in Framed-Compression, if neccessary */
87
88	if (ctype != 0)
89	{
90		if (rc_avpair_add(&send, PW_FRAMED_COMPRESSION, &ctype, 0, VENDOR_NONE) == NULL)
91			return (LFUNC) NULL;
92	}
93
94	/*
95	 * Fill in User-Name
96	 */
97
98	 strncpy(username_realm, username, sizeof(username_realm));
99
100	 /* Append default realm */
101	 default_realm = rc_conf_str("default_realm");
102
103	 if ((strchr(username_realm, '@') == NULL) && default_realm &&
104	     ((*default_realm) != '\0'))
105	 {
106		strncat(username_realm, "@", sizeof(username_realm));
107		strncat(username_realm, default_realm, sizeof(username_realm));
108	 }
109
110	if (rc_avpair_add(&send, PW_USER_NAME, username_realm, 0, VENDOR_NONE) == NULL)
111		return (LFUNC) NULL;
112
113	/*
114	 * Fill in User-Password
115	 */
116
117	if (rc_avpair_add(&send, PW_USER_PASSWORD, passwd, 0, VENDOR_NONE) == NULL)
118		return (LFUNC) NULL;
119
120	result = rc_auth(client_port, send, &received, msg, NULL);
121
122	if (result == OK_RC)
123	{
124		/* Set up a running count of attributes saved. */
125		int acount[256], attr;
126
127		memset(acount, 0, sizeof(acount));
128
129		rc_add_env(env, "RADIUS_USER_NAME", username);
130
131		vp = received;
132
133		/* map-- keep track of the attributes so that we know
134		   when to add the delimiters. Note that we can only
135		   handle attributes < 256, which is the standard anyway. */
136
137		while (vp)
138		{
139			strcpy(name, "RADIUS_");
140			if (rc_avpair_tostr(vp, name+7, sizeof(name)-7, value, sizeof(value)) < 0) {
141				rc_avpair_free(send);
142				rc_avpair_free(received);
143				return (LFUNC) NULL;
144			}
145
146			/* Translate "-" => "_" and uppercase*/
147			for(p = name; *p; p++) {
148				*p = toupper(*p);
149				if (*p == '-') *p = '_';
150			}
151
152			/* Add to the attribute count and append the var
153			   if necessary. */
154			if ((attr = vp->attribute) < 256)
155			{
156				int count;
157				if ((count = acount[attr]++) > 0) {
158					char buf[10];
159					sprintf(buf, "_%d", count);
160					strcat(name,buf);
161				}
162			}
163
164			if (rc_add_env(env, name, value) < 0)
165			{
166				rc_avpair_free(send);
167				rc_avpair_free(received);
168				return (LFUNC) NULL;
169			}
170
171			vp = vp->next;
172		}
173
174		service_str = "(unknown)";
175		ftype_str = NULL;
176
177		if ((service_vp = rc_avpair_get(received, PW_SERVICE_TYPE)) != NULL)
178				if ((dval = rc_dict_getval(service_vp->lvalue, service_vp->name)) != NULL) {
179					service_str = dval->name;
180				}
181
182		if (service_vp && (service_vp->lvalue == PW_FRAMED) &&
183			((vp = rc_avpair_get(received, PW_FRAMED_PROTOCOL)) != NULL))
184				if ((dval = rc_dict_getval(vp->lvalue, vp->name)) != NULL) {
185					ftype_str = dval->name;
186				}
187
188		rc_log(LOG_NOTICE, "authentication OK, username %s, service %s%s%s",
189				username, service_str,(ftype_str)?"/":"", (ftype_str)?ftype_str:"");
190
191		if (msg && (*msg != '\0'))
192			printf(SC_SERVER_REPLY, msg);
193		else
194			printf(SC_RADIUS_OK);
195
196		rc_avpair_free(send);
197		rc_avpair_free(received);
198
199		return radius_login;
200	}
201	else
202	{
203		rc_log(LOG_NOTICE, "authentication FAILED, type RADIUS, username %s",
204			   username_realm);
205		if (msg && (*msg != '\0'))
206			printf(SC_SERVER_REPLY, msg);
207		else
208			printf(SC_RADIUS_FAILED);
209	}
210
211	rc_avpair_free(send);
212	if (received)
213		rc_avpair_free(received);
214
215	return (LFUNC) NULL;
216}
217
218void
219radius_login(char *username)
220{
221	char *login_radius = rc_conf_str("login_radius");
222
223	execle(login_radius, login_radius, NULL, env->env);
224
225	rc_log(LOG_ERR, "couldn't execute %s: %s", login_radius, strerror(errno));
226	fprintf(stderr, "couldn't execute %s: %s", login_radius, strerror(errno));
227
228	sleep(1);	/* give the user time to read */
229	exit(ERROR_RC);
230}
231