Annotation of embedaddon/libpdel/ppp/ppp_auth_pap.c, revision 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>