Annotation of embedaddon/libpdel/ppp/ppp_auth_pap.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (c) 2001-2002 Packet Design, LLC.
4: * All rights reserved.
5: *
6: * Subject to the following obligations and disclaimer of warranty,
7: * use and redistribution of this software, in source or object code
8: * forms, with or without modifications are expressly permitted by
9: * Packet Design; provided, however, that:
10: *
11: * (i) Any and all reproductions of the source or object code
12: * must include the copyright notice above and the following
13: * disclaimer of warranties; and
14: * (ii) No rights are granted, in any manner or form, to use
15: * Packet Design trademarks, including the mark "PACKET DESIGN"
16: * on advertising, endorsements, or otherwise except as such
17: * appears in the above copyright notice or in the software.
18: *
19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
36: * THE POSSIBILITY OF SUCH DAMAGE.
37: *
38: * Author: Archie Cobbs <archie@freebsd.org>
39: */
40:
41: #include "ppp/ppp_defs.h"
42: #include "ppp/ppp_log.h"
43: #include "ppp/ppp_fsm_option.h"
44: #include "ppp/ppp_fsm.h"
45: #include "ppp/ppp_auth.h"
46: #include "ppp/ppp_link.h"
47: #include "ppp/ppp_auth_pap.h"
48:
49: #define PAP_MTYPE "ppp_authtype.pap"
50:
51: #define PAP_RETRY 3
52:
53: #define PAP_REQUEST 1
54: #define PAP_ACK 2
55: #define PAP_NAK 3
56:
57: #define PAP_MSG_ACK "Authorization successful"
58: #define PAP_MSG_NAK "Authorization failed"
59: #define PAP_MSG_BUFSIZE 64
60:
61: /* PAP info structure */
62: struct ppp_auth_pap {
63: struct ppp_link *link;
64: struct ppp_log *log;
65: struct ppp_auth_config aconf;
66: struct ppp_auth_cred cred;
67: struct ppp_auth_resp resp;
68: int dir;
69: u_char id;
70: struct pevent_ctx *ev_ctx;
71: struct pevent *timer;
72: pthread_mutex_t *mutex;
73: };
74:
75: /* Internal functions */
76: static void ppp_auth_pap_send_request(struct ppp_auth_pap *pap);
77: static void ppp_auth_pap_send_response(struct ppp_auth_pap *pap,
78: u_char id, int ack);
79:
80: static ppp_link_auth_finish_t ppp_auth_pap_acquire_finish;
81: static ppp_link_auth_finish_t ppp_auth_pap_check_finish;
82:
83: /* Internal variables */
84: static const char *pap_codes[] = {
85: "zero",
86: "request",
87: "ack",
88: "nak"
89: };
90:
91: /* Macro for logging */
92: #define LOG(sev, fmt, args...) PPP_LOG(pap->log, sev, fmt , ## args)
93:
94: /*
95: * Start PAP
96: */
97: void *
98: ppp_auth_pap_start(struct pevent_ctx *ev_ctx, struct ppp_link *link,
99: pthread_mutex_t *mutex, int dir, u_int16_t *protop, struct ppp_log *log)
100: {
101: struct ppp_auth_pap *pap;
102:
103: /* Create info structure */
104: if ((pap = MALLOC(PAP_MTYPE, sizeof(*pap))) == NULL)
105: return (NULL);
106: memset(pap, 0, sizeof(*pap));
107: pap->ev_ctx = ev_ctx;
108: pap->mutex = mutex;
109: pap->link = link;
110: pap->log = log;
111: pap->dir = dir;
112: pap->cred.type = PPP_AUTH_PAP;
113:
114: /* Get link auth config */
115: pap->aconf = *ppp_link_auth_get_config(link);
116:
117: /* Return protocol */
118: *protop = PPP_PROTO_PAP;
119:
120: /* If receiving auth, wait for peer's request */
121: if (dir == PPP_SELF)
122: return (pap);
123:
124: /* If sending auth, acquire credentials */
125: if (ppp_link_authorize(pap->link, pap->dir,
126: &pap->cred, ppp_auth_pap_acquire_finish) == -1) {
127: FREE(PAP_MTYPE, pap);
128: return (NULL);
129: }
130:
131: /* Done */
132: return (pap);
133: }
134:
135: /*
136: * Cancel PAP
137: */
138: void
139: ppp_auth_pap_cancel(void *arg)
140: {
141: struct ppp_auth_pap *pap = arg;
142:
143: pevent_unregister(&pap->timer);
144: ppp_log_close(&pap->log);
145: FREE(PAP_MTYPE, pap);
146: }
147:
148: /*
149: * Handle PAP input
150: */
151: void
152: ppp_auth_pap_input(void *arg, int dir, void *data, size_t len)
153: {
154: struct ppp_auth_pap *pap = arg;
155: struct ppp_fsm_pkt *const pkt = data;
156:
157: if (len < sizeof(*pkt) + 2)
158: return;
159: memcpy(pkt, data, sizeof(*pkt));
160: pkt->length = ntohs(pkt->length);
161: if (pkt->length > len)
162: return;
163: if (pkt->length < len)
164: len = pkt->length;
165: len -= sizeof(*pkt);
166: switch (pkt->code) {
167: case PAP_REQUEST:
168: {
169: struct ppp_auth_cred_pap *const cred = &pap->cred.u.pap;
170: u_char nlen;
171: u_char plen;
172:
173: /* Check direction */
174: if (dir != PPP_SELF)
175: break;
176:
177: /* Logging */
178: LOG(LOG_DEBUG, "rec'd %s #%u", pap_codes[pkt->code], pkt->id);
179:
180: /* Extract username and password */
181: if (len < 1)
182: return;
183: nlen = pkt->data[0];
184: if (len < 1 + nlen + 1)
185: return;
186: plen = pkt->data[1 + nlen];
187: if (len < 1 + nlen + 1 + plen)
188: return;
189: strncpy(cred->name, pkt->data + 1,
190: MIN(nlen, sizeof(cred->name) - 1));
191: cred->name[sizeof(cred->name) - 1] = '\0';
192: strncpy(cred->password, pkt->data + 1 + nlen + 1,
193: MIN(plen, sizeof(cred->password) - 1));
194: cred->password[sizeof(cred->password) - 1] = '\0';
195:
196: /* Ignore if already checking a previous request */
197: if (ppp_link_auth_in_progress(pap->link, pap->dir)) {
198: LOG(LOG_DEBUG, "ignoring packet, action pending");
199: break;
200: }
201:
202: /* Check credentials */
203: if (ppp_link_authorize(pap->link, pap->dir,
204: &pap->cred, ppp_auth_pap_check_finish) == -1) {
205: ppp_auth_pap_send_response(pap, pap->id, 0);
206: ppp_link_auth_complete(pap->link, pap->dir, NULL, NULL);
207: break;
208: }
209:
210: /* Save peer's id for my response */
211: pap->id = pkt->id;
212:
213: /* Now wait for credentials check to finish */
214: break;
215: }
216: case PAP_ACK:
217: case PAP_NAK:
218:
219: /* Check direction */
220: if (dir != PPP_PEER)
221: break;
222:
223: /* Logging */
224: LOG(LOG_DEBUG, "rec'd %s #%u", pap_codes[pkt->code], pkt->id);
225:
226: /* Stop timer */
227: pevent_unregister(&pap->timer);
228:
229: /* Finish up */
230: ppp_link_auth_complete(pap->link, pap->dir,
231: pkt->code == PAP_ACK ? &pap->cred : NULL, NULL);
232: break;
233: default:
234: return;
235: }
236: }
237:
238: /*
239: * Continue after a successful credentials acquisition.
240: */
241: static void
242: ppp_auth_pap_acquire_finish(void *arg,
243: const struct ppp_auth_cred *creds, const struct ppp_auth_resp *resp)
244: {
245: struct ppp_auth_pap *const pap = arg;
246: struct ppp_auth_cred_pap *const cred = &pap->cred.u.pap;
247:
248: /* Copy credentials */
249: pap->cred = *creds;
250:
251: /* Sanitize credentials */
252: cred->name[sizeof(cred->name) - 1] = '\0';
253: cred->password[sizeof(cred->password) - 1] = '\0';
254:
255: /* Send first PAP request */
256: ppp_auth_pap_send_request(pap);
257: }
258:
259: /*
260: * Continue after a successful credentials check.
261: */
262: static void
263: ppp_auth_pap_check_finish(void *arg,
264: const struct ppp_auth_cred *creds, const struct ppp_auth_resp *resp)
265: {
266: struct ppp_auth_pap *const pap = arg;
267: struct ppp_auth_cred_pap *const cred = &pap->cred.u.pap;
268: int valid = (*resp->errmsg == '\0');
269:
270: /* Copy response */
271: pap->resp = *resp;
272:
273: /* Report validity */
274: if (valid) {
275: LOG(LOG_INFO, "rec'd %s credentials for \"%s\"",
276: "valid", cred->name);
277: } else {
278: LOG(LOG_NOTICE, "rec'd %s credentials for \"%s\": %s",
279: "invalid", cred->name, resp->errmsg);
280: }
281:
282: /* Send response */
283: ppp_auth_pap_send_response(pap, pap->id, valid);
284:
285: /* Finish up */
286: ppp_link_auth_complete(pap->link,
287: pap->dir, valid ? &pap->cred : NULL, NULL);
288: }
289:
290: /*
291: * Send a PAP request
292: */
293: static void
294: ppp_auth_pap_send_request(struct ppp_auth_pap *pap)
295: {
296: struct ppp_auth_cred_pap *const cred = &pap->cred.u.pap;
297: union {
298: u_char buf[sizeof(struct ppp_fsm_pkt)
299: + sizeof(cred->name) + sizeof(cred->password)];
300: struct ppp_fsm_pkt pkt;
301: } u;
302: struct ppp_fsm_pkt *const pkt = &u.pkt;
303:
304: /* Cancel previous timeout event (if any) and start another */
305: pevent_unregister(&pap->timer);
306: if (pevent_register(pap->ev_ctx, &pap->timer, 0,
307: pap->mutex, (pevent_handler_t *)ppp_auth_pap_send_request,
308: pap, PEVENT_TIME, PAP_RETRY * 1000) == -1)
309: LOG(LOG_ERR, "%s: %m", "pevent_register");
310:
311: /* Construct packet */
312: pkt->id = ++pap->id;
313: pkt->code = PAP_REQUEST;
314: pkt->length = htons(sizeof(*pkt)
315: + 1 + strlen(cred->name) + 1 + strlen(cred->password));
316: pkt->data[0] = strlen(cred->name);
317: memcpy(pkt->data + 1, cred->name, strlen(cred->name));
318: pkt->data[1 + strlen(cred->name)] = strlen(cred->password);
319: memcpy(pkt->data + 1 + strlen(cred->name) + 1,
320: cred->password, strlen(cred->password));
321:
322: /* Logging */
323: LOG(LOG_DEBUG, "xmit %s #%u", pap_codes[pkt->code], pkt->id);
324:
325: /* Send packet */
326: ppp_link_write(pap->link, PPP_PROTO_PAP, pkt, ntohs(pkt->length));
327: }
328:
329: /*
330: * Send a PAP response
331: */
332: static void
333: ppp_auth_pap_send_response(struct ppp_auth_pap *pap, u_char id, int ack)
334: {
335: union {
336: u_char buf[sizeof(struct ppp_fsm_pkt) + 1 + PAP_MSG_BUFSIZE];
337: struct ppp_fsm_pkt pkt;
338: } u;
339: struct ppp_fsm_pkt *const pkt = &u.pkt;
340:
341: /* Construct packet */
342: pkt->id = id;
343: pkt->code = ack ? PAP_ACK : PAP_NAK;
344: snprintf(pkt->data + 1, PAP_MSG_BUFSIZE,
345: "%s", ack ? PAP_MSG_ACK : PAP_MSG_NAK);
346: pkt->data[0] = strlen(pkt->data + 1);
347: pkt->length = htons(sizeof(*pkt) + 1 + strlen(pkt->data + 1));
348:
349: /* Logging */
350: LOG(LOG_DEBUG, "xmit %s #%u", pap_codes[pkt->code], pkt->id);
351:
352: /* Send packet */
353: ppp_link_write(pap->link, PPP_PROTO_PAP, pkt, ntohs(pkt->length));
354: }
355:
356:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>