Commented out the ld -x -r lines and put NOPIC wrappers around the
[unix-history] / libexec / pppd / upap.c
CommitLineData
2a905848
RG
1/*
2 * upap.c - User/Password Authentication Protocol.
3 *
4 * Copyright (c) 1989 Carnegie Mellon University.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by Carnegie Mellon University. The name of the
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20/*
21 * TODO:
22 */
23
24#include <stdio.h>
25#include <sys/types.h>
26#include <sys/time.h>
27#include <syslog.h>
28
29#ifdef STREAMS
30#include <sys/socket.h>
31#include <net/if.h>
32#include <sys/stream.h>
33#endif
34
35#include <net/ppp.h>
36#include "pppd.h"
37#include "fsm.h"
38#include "lcp.h"
39#include "upap.h"
40#include "chap.h"
41#include "ipcp.h"
42
43
44upap_state upap[NPPP]; /* UPAP state; one for each unit */
45
46
47static void upap_timeout __ARGS((caddr_t));
48static void upap_rauth __ARGS((upap_state *, u_char *, int, int));
49static void upap_rauthack __ARGS((upap_state *, u_char *, int, int));
50static void upap_rauthnak __ARGS((upap_state *, u_char *, int, int));
51static void upap_sauth __ARGS((upap_state *));
52static void upap_sresp __ARGS((upap_state *, int, int, u_char *, int));
53
54
55/*
56 * upap_init - Initialize a UPAP unit.
57 */
58void
59 upap_init(unit)
60int unit;
61{
62 upap_state *u = &upap[unit];
63
64 u->us_unit = unit;
65 u->us_user = NULL;
66 u->us_userlen = 0;
67 u->us_passwd = NULL;
68 u->us_passwdlen = 0;
69 u->us_clientstate = UPAPCS_CLOSED;
70 u->us_serverstate = UPAPSS_CLOSED;
71 u->us_flags = 0;
72 u->us_id = 0;
73 u->us_timeouttime = UPAP_DEFTIMEOUT;
74}
75
76
77/*
78 * upap_authwithpeer - Authenticate us with our peer (start client).
79 *
80 * Set new state and send authenticate's.
81 */
82void
83 upap_authwithpeer(unit)
84int unit;
85{
86 upap_state *u = &upap[unit];
87
88 u->us_flags &= ~UPAPF_AWPPENDING; /* Clear pending flag */
89
90 /* Protect against programming errors that compromise security */
91 if (u->us_serverstate != UPAPSS_CLOSED ||
92 u->us_flags & UPAPF_APPENDING) {
93 UPAPDEBUG((LOG_WARNING,
94 "upap_authwithpeer: upap_authpeer already called!"))
95 return;
96 }
97
98 /* Already authenticat{ed,ing}? */
99 if (u->us_clientstate == UPAPCS_AUTHSENT ||
100 u->us_clientstate == UPAPCS_OPEN)
101 return;
102
103 /* Lower layer up? */
104 if (!(u->us_flags & UPAPF_LOWERUP)) {
105 u->us_flags |= UPAPF_AWPPENDING; /* Wait */
106 return;
107 }
108
109 /* User/passwd values valid? */
110 if (!(u->us_flags & UPAPF_UPVALID)) {
111 GETUSERPASSWD(unit); /* Start getting user and passwd */
112 if (!(u->us_flags & UPAPF_UPVALID)) {
113 u->us_flags |= UPAPF_UPPENDING; /* Wait */
114 return;
115 }
116 }
117
118 upap_sauth(u); /* Start protocol */
119/* TIMEOUT(upap_timeout, (caddr_t) u, u->us_timeouttime);*/
120 u->us_clientstate = UPAPCS_AUTHSENT;
121 u->us_retransmits = 0;
122}
123
124
125/*
126 * upap_authpeer - Authenticate our peer (start server).
127 *
128 * Set new state.
129 */
130void
131 upap_authpeer(unit)
132int unit;
133{
134 upap_state *u = &upap[unit];
135
136 u->us_flags &= ~UPAPF_APPENDING; /* Clear pending flag */
137
138 /* Already authenticat{ed,ing}? */
139 if (u->us_serverstate == UPAPSS_LISTEN ||
140 u->us_serverstate == UPAPSS_OPEN)
141 return;
142
143 /* Lower layer up? */
144 if (!(u->us_flags & UPAPF_LOWERUP)) {
145 u->us_flags |= UPAPF_APPENDING; /* Wait for desired event */
146 return;
147 }
148 u->us_serverstate = UPAPSS_LISTEN;
149}
150
151
152/*
153 * upap_timeout - Timeout expired.
154 */
155static void
156 upap_timeout(arg)
157caddr_t arg;
158{
159 upap_state *u = (upap_state *) arg;
160
161 if (u->us_clientstate != UPAPCS_AUTHSENT)
162 return;
163
164 /* XXX Print warning after many retransmits? */
165
166 upap_sauth(u); /* Send Configure-Request */
167 TIMEOUT(upap_timeout, (caddr_t) u, u->us_timeouttime);
168 ++u->us_retransmits;
169}
170
171
172/*
173 * upap_lowerup - The lower layer is up.
174 *
175 * Start authenticating if pending.
176 */
177void
178 upap_lowerup(unit)
179int unit;
180{
181 upap_state *u = &upap[unit];
182
183 u->us_flags |= UPAPF_LOWERUP;
184 if (u->us_flags & UPAPF_AWPPENDING) /* Attempting authwithpeer? */
185 upap_authwithpeer(unit); /* Try it now */
186 if (u->us_flags & UPAPF_APPENDING) /* Attempting authpeer? */
187 upap_authpeer(unit); /* Try it now */
188}
189
190
191/*
192 * upap_lowerdown - The lower layer is down.
193 *
194 * Cancel all timeouts.
195 */
196void
197 upap_lowerdown(unit)
198int unit;
199{
200 upap_state *u = &upap[unit];
201
202 u->us_flags &= ~UPAPF_LOWERUP; /* XXX UPAP_UPVALID? */
203
204 if (u->us_clientstate == UPAPCS_AUTHSENT) /* Timeout pending? */
205 UNTIMEOUT(upap_timeout, (caddr_t) u); /* Cancel timeout */
206
207 if (u->us_serverstate == UPAPSS_OPEN) /* User logged in? */
208 LOGOUT(unit);
209 u->us_clientstate = UPAPCS_CLOSED;
210 u->us_serverstate = UPAPSS_CLOSED;
211}
212
213
214/*
215 * upap_protrej - Peer doesn't speak this protocol.
216 *
217 * This shouldn't happen. In any case, pretend lower layer went down.
218 */
219void
220 upap_protrej(unit)
221int unit;
222{
223 upap_lowerdown(unit);
224}
225
226
227/*
228 * upap_input - Input UPAP packet.
229 */
230void
231 upap_input(unit, inpacket, l)
232int unit;
233u_char *inpacket;
234int l;
235{
236 upap_state *u = &upap[unit];
237 u_char *inp;
238 u_char code, id;
239 int len;
240
241 /*
242 * Parse header (code, id and length).
243 * If packet too short, drop it.
244 */
245 inp = inpacket;
246 if (l < UPAP_HEADERLEN) {
247 UPAPDEBUG((LOG_INFO, "upap_input: rcvd short header."))
248 return;
249 }
250 GETCHAR(code, inp);
251 GETCHAR(id, inp);
252 GETSHORT(len, inp);
253 if (len < UPAP_HEADERLEN) {
254 UPAPDEBUG((LOG_INFO, "upap_input: rcvd illegal length."))
255 return;
256 }
257 if (len > l) {
258 UPAPDEBUG((LOG_INFO, "upap_input: rcvd short packet."))
259 return;
260 }
261 len -= UPAP_HEADERLEN;
262
263 /*
264 * Action depends on code.
265 */
266 switch (code) {
267 case UPAP_AUTH:
268 upap_rauth(u, inp, id, len);
269 break;
270
271 case UPAP_AUTHACK:
272 upap_rauthack(u, inp, id, len);
273 break;
274
275 case UPAP_AUTHNAK:
276 upap_rauthnak(u, inp, id, len);
277 break;
278
279 default: /* XXX Need code reject */
280 break;
281 }
282}
283
284
285/*
286 * upap_rauth - Receive Authenticate.
287 */
288static void
289 upap_rauth(u, inp, id, len)
290upap_state *u;
291u_char *inp;
292u_char id;
293int len;
294{
295 u_char ruserlen, rpasswdlen;
296 u_char *ruser, *rpasswd;
297 u_char retcode;
298 u_char *msg;
299 int msglen;
300
301 UPAPDEBUG((LOG_INFO, "upap_rauth: Rcvd id %d.", id))
302 if (u->us_serverstate != UPAPSS_LISTEN) /* XXX Reset connection? */
303 return;
304
305 /*
306 * Parse user/passwd.
307 */
308 if (len < sizeof (u_char)) {
309 UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet."))
310 return;
311 }
312 GETCHAR(ruserlen, inp);
313 len -= sizeof (u_char) + ruserlen + sizeof (u_char);;
314 if (len < 0) {
315 UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet."))
316 return;
317 }
318 ruser = inp;
319 INCPTR(ruserlen, inp);
320 GETCHAR(rpasswdlen, inp);
321 if (len < rpasswdlen) {
322 UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet."))
323 return;
324 }
325 rpasswd = inp;
326
327 retcode = LOGIN(u->us_unit, (char *) ruser, (int) ruserlen, (char *) rpasswd,
328 (int) rpasswdlen, (char **) &msg, &msglen);
329
330 upap_sresp(u, retcode, id, msg, msglen);
331
332 /* only crank up IPCP when either we aren't doing CHAP, or if we are, */
333 /* that it is in open state */
334
335 if (retcode == UPAP_AUTHACK) {
336 u->us_serverstate = UPAPSS_OPEN;
337 if (!lcp_hisoptions[u->us_unit].neg_chap ||
338 (lcp_hisoptions[u->us_unit].neg_chap &&
339 chap[u->us_unit].serverstate == CHAPSS_OPEN))
340 ipcp_activeopen(u->us_unit); /* Start IPCP */
341 }
342}
343
344
345/*
346 * upap_rauthack - Receive Authenticate-Ack.
347 */
348static void
349 upap_rauthack(u, inp, id, len)
350upap_state *u;
351u_char *inp;
352u_char id;
353int len;
354{
355 u_char msglen;
356 u_char *msg;
357
358 UPAPDEBUG((LOG_INFO, "upap_rauthack: Rcvd id %d.", id))
359 if (u->us_clientstate != UPAPCS_AUTHSENT) /* XXX */
360 return;
361
362 /*
363 * Parse message.
364 */
365 if (len < sizeof (u_char)) {
366 UPAPDEBUG((LOG_INFO, "upap_rauthack: rcvd short packet."))
367 return;
368 }
369 GETCHAR(msglen, inp);
370 len -= sizeof (u_char);
371 if (len < msglen) {
372 UPAPDEBUG((LOG_INFO, "upap_rauthack: rcvd short packet."))
373 return;
374 }
375 msg = inp;
376 PRINTMSG(msg, msglen);
377
378 u->us_clientstate = UPAPCS_OPEN;
379
380 /* only crank up IPCP when either we aren't doing CHAP, or if we are, */
381 /* that it is in open state */
382
383 if (!lcp_gotoptions[u->us_unit].neg_chap ||
384 (lcp_gotoptions[u->us_unit].neg_chap &&
385 chap[u->us_unit].clientstate == CHAPCS_OPEN))
386 ipcp_activeopen(u->us_unit); /* Start IPCP */
387}
388
389
390/*
391 * upap_rauthnak - Receive Authenticate-Nakk.
392 */
393static void
394 upap_rauthnak(u, inp, id, len)
395upap_state *u;
396u_char *inp;
397u_char id;
398int len;
399{
400 u_char msglen;
401 u_char *msg;
402
403 UPAPDEBUG((LOG_INFO, "upap_rauthnak: Rcvd id %d.", id))
404 if (u->us_clientstate != UPAPCS_AUTHSENT) /* XXX */
405 return;
406
407 /*
408 * Parse message.
409 */
410 if (len < sizeof (u_char)) {
411 UPAPDEBUG((LOG_INFO, "upap_rauthnak: rcvd short packet."))
412 return;
413 }
414 GETCHAR(msglen, inp);
415 len -= sizeof (u_char);
416 if (len < msglen) {
417 UPAPDEBUG((LOG_INFO, "upap_rauthnak: rcvd short packet."))
418 return;
419 }
420 msg = inp;
421 PRINTMSG(msg, msglen);
422
423 u->us_flags &= ~UPAPF_UPVALID; /* Clear valid flag */
424 u->us_clientstate = UPAPCS_CLOSED; /* Pretend for a moment */
425 upap_authwithpeer(u->us_unit); /* Restart */
426}
427
428
429/*
430 * upap_sauth - Send an Authenticate.
431 */
432static void
433 upap_sauth(u)
434upap_state *u;
435{
436 u_char *outp;
437 int outlen;
438
439 outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
440 u->us_userlen + u->us_passwdlen;
441 outp = outpacket_buf;
442
443 MAKEHEADER(outp, UPAP);
444
445 PUTCHAR(UPAP_AUTH, outp);
446 PUTCHAR(++u->us_id, outp);
447 PUTSHORT(outlen, outp);
448 PUTCHAR(u->us_userlen, outp);
449 BCOPY(u->us_user, outp, u->us_userlen);
450 INCPTR(u->us_userlen, outp);
451 PUTCHAR(u->us_passwdlen, outp);
452 BCOPY(u->us_passwd, outp, u->us_passwdlen);
453 output(u->us_unit, outpacket_buf, outlen + DLLHEADERLEN);
454
455 UPAPDEBUG((LOG_INFO, "upap_sauth: Sent id %d.", u->us_id))
456}
457
458
459/*
460 * upap_sresp - Send a response (ack or nak).
461 */
462static void
463 upap_sresp(u, code, id, msg, msglen)
464upap_state *u;
465u_char code, id;
466u_char *msg;
467int msglen;
468{
469 u_char *outp;
470 int outlen;
471
472 outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
473 outp = outpacket_buf;
474 MAKEHEADER(outp, UPAP);
475
476 PUTCHAR(code, outp);
477 PUTCHAR(id, outp);
478 PUTSHORT(outlen, outp);
479 PUTCHAR(msglen, outp);
480 BCOPY(msg, outp, msglen);
481 output(u->us_unit, outpacket_buf, outlen + DLLHEADERLEN);
482
483 UPAPDEBUG((LOG_INFO, "upap_sresp: Sent code %d, id %d.", code, id))
484}