]> git.ozlabs.org Git - ppp.git/blob - pppd/plugins/radius/radiusclient/src/radlogin.c
Added RADIUS suppport.
[ppp.git] / pppd / plugins / radius / radiusclient / src / radlogin.c
1 /*
2  * $Id: radlogin.c,v 1.1 2002/01/22 16:03:04 dfs Exp $
3  *
4  * Copyright (C) 1995,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 static char     rcsid[] =
13                 "$Id: radlogin.c,v 1.1 2002/01/22 16:03:04 dfs Exp $";
14
15 #include        <config.h>
16 #include        <includes.h>
17 #include        <radiusclient.h>
18 #include        <messages.h>
19 #include        <pathnames.h>
20 #include        <radlogin.h>
21
22 ENV *env = NULL;
23 static char *pname = NULL;
24
25 static RETSIGTYPE
26 alarm_handler(int sn)
27 {
28         fprintf(stderr, SC_TIMEOUT, rc_conf_int("login_timeout"));
29         sleep(1);
30         exit(ERROR_RC); 
31 }
32
33 static int
34 login_allowed(char *tty)
35 {
36         FILE *fp;
37         char fname[PATH_MAX];
38         int c;
39
40         strcpy(fname, rc_conf_str("nologin"));
41         if (access(fname, F_OK) < 0) {
42                 if (tty) {
43                         sprintf(fname, "%s.%s", rc_conf_str("nologin"), tty);
44                         if (access(fname, F_OK) < 0)
45                                 return 1;
46                 } else {
47                         return 1;
48                 }
49         }
50
51         if ((fp = fopen(fname, "r")) != NULL)
52         {
53                 while ((c = fgetc(fp)) != EOF)
54                 {
55                         if (c == '\n')
56                                 fputc('\r', stdout);
57                         fputc(c, stdout);
58                 }
59                 fflush(stdout);
60                 fclose(fp);
61         } else {
62                 printf(SC_NOLOGIN);
63         }
64         return (0);             
65 }
66
67 static char *
68 subst_placeholders(char *str, char *tty)
69 {
70         char *p,*q;
71         static char buf[4096];
72 #if defined(HAVE_UNAME)
73         struct utsname uts;
74 #endif
75 #if !defined(HAVE_STRUCT_UTSNAME_DOMAINNAME) && defined(HAVE_GETDOMAINNAME)
76         char domainname[256];
77 #endif
78
79 #if defined(HAVE_UNAME) 
80         uname(&uts);
81 #endif
82         
83         p = str;
84         q = buf;        
85
86         while (*p != '\0') {
87                 switch (*p) {
88                         case '\\':
89                                 if (*(p+1) == '\0')
90                                         break;
91                                 p++;
92                                 switch (*p) {
93                                         case 'I':
94                                                 strcpy(q, rcsid);
95                                                 q += strlen(rcsid);
96                                                 break;
97                                         case 'L':
98                                         case 'P':
99                                                 strcpy(q, tty);
100                                                 q += strlen(tty);
101                                                 break;
102 #if defined(HAVE_UNAME)
103                                         case 'S':
104                                                 strcpy(q, uts.sysname);
105                                                 q += strlen(uts.sysname);
106                                                 break;
107                                         case 'N':
108                                                 strcpy(q, uts.nodename);
109                                                 q += strlen(uts.nodename);
110                                                 break;
111                                         case 'R':
112                                                 strcpy(q, uts.release);
113                                                 q += strlen(uts.release);
114                                                 break;
115                                         case 'V':
116                                                 strcpy(q, uts.version);
117                                                 q += strlen(uts.version);
118                                                 break;
119                                         case 'M':
120                                                 strcpy(q, uts.machine);
121                                                 q += strlen(uts.machine);
122                                                 break;
123 #endif
124                                         case 'D':
125 #if defined(HAVE_STRUCT_UTSNAME_DOMAINNAME)
126                                                 strcpy(q, uts.domainname);
127                                                 q += strlen(uts.domainname);
128 #elif defined(HAVE_GETDOMAINNAME)
129                                                 getdomainname(domainname, sizeof(domainname));
130                                                 strcpy(q, domainname);
131                                                 q += strlen(domainname);
132 #endif
133                                                 break;
134                                         case '\\':
135                                                 *q = '\\';
136                                                 q++;
137                                                 break;
138                                 }
139                                 break;
140 #if defined(HAVE_UNAME)
141                         case '@':
142                                 strcpy(q, uts.nodename);
143                                 q += strlen(uts.nodename);
144                                 break;
145 #endif
146                         case '\n':
147                                 strcpy(q,"\r\n");
148                                 q += 2;
149                                 break;
150                         default:
151                                 *q = *p;
152                                 q++;
153                                 break;
154                 }
155
156                 p++;
157         }
158         *q = '\0';
159
160         return buf;
161 }
162
163 static void
164 usage(void)
165 {
166         fprintf(stderr,"Usage: %s [-Vhnd] [-f <config_file>] [-i <client_port>] [-m <login_tries>]\n\n", pname);
167         fprintf(stderr,"  -V            output version information\n");
168         fprintf(stderr,"  -h            output this text\n");     
169         fprintf(stderr,"  -n            don't display issue file\n");
170         fprintf(stderr,"  -f            filename of alternate config file\n");
171         fprintf(stderr,"  -i            ttyname to send to the server\n");
172         fprintf(stderr,"  -m            maximum login tries (overrides value in config file)\n");
173         exit(ERROR_RC);
174 }
175
176 static void
177 version(void)
178 {
179         fprintf(stderr,"%s: %s\n", pname ,rcsid);
180         exit(ERROR_RC);
181 }
182
183 int
184 main (int argc, char **argv)
185 {
186         char            username[128];
187         char            passwd[AUTH_PASS_LEN + 1];
188         int             tries, remaining, c;
189         UINT4           client_port;
190         void            (*login_func)(char *);  
191         FILE            *fp;
192         char            buf[4096];
193         char            tty[1024], *p;
194         int             noissue = 0;
195         int             maxtries = 0;
196         char            *ttyn  = NULL;
197         char            *path_radiusclient_conf = RC_CONFIG_FILE;
198
199         extern char *optarg;
200         extern int optind;
201
202         pname = (pname = strrchr(argv[0],'/'))?pname+1:argv[0];
203         
204         rc_openlog(pname);
205
206         while ((c = getopt(argc,argv,"f:m:i:nhV")) > 0)
207         {
208                 switch(c) {
209                         case 'f':
210                                 path_radiusclient_conf = optarg;
211                                 break;
212                         case 'i':
213                                 ttyn = optarg;
214                                 break;
215                         case 'n':
216                                 noissue = 1;
217                                 break;
218                         case 'm':
219                                 maxtries = atoi(optarg);
220                                 break;
221                         case 'V':
222                                 version();
223                                 break;
224                         case 'h':
225                                 usage();
226                                 break;
227                         default:
228                                 exit(ERROR_RC);
229                                 break;
230                 }
231         }
232
233         if (rc_read_config(path_radiusclient_conf) != 0)
234                 exit(ERROR_RC);
235         
236         if (rc_read_dictionary(rc_conf_str("dictionary")) != 0)
237                 exit (ERROR_RC);
238
239         if (rc_read_mapfile(rc_conf_str("mapfile")) != 0)
240                 exit (ERROR_RC);
241
242         if (ttyn != NULL)
243         {
244                 client_port = rc_map2id(ttyn);
245                 
246                 if ((p = strrchr(ttyn, '/')) == NULL)
247                         strncpy(tty, ttyn, sizeof(tty));
248                 else
249                         strncpy(tty, p+1, sizeof(tty));
250         }
251         else
252         {
253                 ttyn = ttyname(0);
254                 if (ttyn)
255                 {
256                         if ((p = strrchr(ttyn, '/')) == NULL)
257                                 strncpy(tty, ttyn, sizeof(tty));
258                         else
259                                 strncpy(tty, p+1, sizeof(tty));
260
261                         client_port = rc_map2id(ttyn);
262                 }
263                 else 
264                 {
265                         *tty = '\0';
266                         client_port = 0;
267                 }
268         }
269
270 #ifdef SETVBUF_REVERSED
271         setvbuf(stdout, _IONBF, NULL, 0);
272 #else
273         setvbuf(stdout, NULL, _IONBF, 0);
274 #endif
275
276         if ((argc - optind) == 1)
277         {
278                 strncpy(username,argv[optind], sizeof(username));
279         }
280         else
281         {
282                 *username = '\0';
283                 
284                 if (!noissue) {
285                         if (rc_conf_str("issue") && ((fp = fopen(rc_conf_str("issue"), "r")) != NULL))
286                         {
287                                 while (fgets(buf, sizeof(buf), fp) != NULL)
288                                         fputs(subst_placeholders(buf, tty), stdout);
289
290                                 fflush(stdout);
291                                 fclose(fp);
292                         } else {
293                                 fputs(subst_placeholders(SC_DEFAULT_ISSUE, tty), stdout);
294                                 fflush(stdout);
295                         }
296                 }
297         }
298
299         if ((env = rc_new_env(ENV_SIZE)) == NULL)
300         {
301                 rc_log(LOG_CRIT, "rc_new_env: FATAL: out of memory");
302                 abort();
303         }
304         
305 #ifdef SECURITY_DISABLED
306         if (rc_import_env(env,environ) < 0)
307         {
308                 rc_log(LOG_CRIT, "rc_import_env: FATAL: not enough space for environment (increase ENV_SIZE)");
309                 abort();
310         }
311 #else
312         rc_add_env(env, "IFS", " ");
313         rc_add_env(env, "PATH", RC_SECURE_PATH);
314 #endif
315
316         signal(SIGALRM, alarm_handler);
317
318         remaining = rc_conf_int("login_timeout");
319         
320         if (!maxtries)
321                 maxtries = rc_conf_int("login_tries");
322                 
323         tries = 1;
324         while (tries <= maxtries)
325         {
326          alarm(remaining);
327
328          while (!*username) {
329                 p = rc_getstr (SC_LOGIN, 1);
330                 if (p)
331                         strncpy(username, p, sizeof(username));
332                 else
333                         exit (ERROR_RC);
334          }
335          p = rc_getstr(SC_PASSWORD,0);
336          if (p) 
337                 strncpy (passwd, p, sizeof (passwd));           
338          else 
339                 exit (ERROR_RC);
340
341          remaining = alarm(0);
342          
343          login_func = NULL;
344
345          if (rc_conf_int("auth_order") & AUTH_LOCAL_FST)
346          {
347                 login_func = auth_local(username, passwd);
348                         
349                 if (!login_func)
350                         if (rc_conf_int("auth_order") & AUTH_RADIUS_SND)
351                                 login_func = auth_radius(client_port, username, passwd);
352          }
353          else
354          {
355                 login_func = auth_radius(client_port, username, passwd);
356                 if (!login_func)
357                         if (rc_conf_int("auth_order") & AUTH_LOCAL_SND)
358                                 login_func = auth_local(username, passwd);
359          }
360
361          memset(passwd, '\0', sizeof(passwd));
362
363          if (login_func != NULL)
364                 if (login_allowed(tty)) {
365                         (*login_func)(username);
366                 } else {
367                         sleep(1);
368                         exit (ERROR_RC);
369                 }
370
371          *username = '\0';
372          
373          if ((++tries) <= maxtries) {
374                 alarm(remaining);
375                 sleep(tries * 2);
376                 remaining = alarm(0);
377          }
378
379         }
380
381         fprintf(stderr, SC_EXCEEDED);
382         sleep(1);
383         
384         exit (ERROR_RC);
385 }