]> git.ozlabs.org Git - ppp.git/blob - pppd/plugins/radius/radiusclient/src/radius.c
Added RADIUS suppport.
[ppp.git] / pppd / plugins / radius / radiusclient / src / radius.c
1 /*
2  * $Id: radius.c,v 1.1 2002/01/22 16:03:04 dfs 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
18 extern ENV *env;
19
20 LFUNC 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);
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
218 void
219 radius_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 }