[BACK]Return to auth.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / telnet

Annotation of src/usr.bin/telnet/auth.c, Revision 1.1

1.1     ! deraadt     1: /*     $OpenBSD: auth.c,v 1.2 2003/06/02 19:38:24 millert Exp $    */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 1991, 1993
        !             5:  *     The Regents of the University of California.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. Neither the name of the University nor the names of its contributors
        !            16:  *    may be used to endorse or promote products derived from this software
        !            17:  *    without specific prior written permission.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            29:  * SUCH DAMAGE.
        !            30:  */
        !            31:
        !            32: #ifndef lint
        !            33: /* from: static char sccsid[] = "@(#)auth.c    8.3 (Berkeley) 5/30/95" */
        !            34: /* from: static char *rcsid = "$NetBSD: auth.c,v 1.5 1996/02/24 01:15:17 jtk Exp $"; */
        !            35: #endif /* not lint */
        !            36:
        !            37: /*
        !            38:  * This source code is no longer held under any constraint of USA
        !            39:  * `cryptographic laws' since it was exported legally.  The cryptographic
        !            40:  * functions were removed from the code and a "Bones" distribution was
        !            41:  * made.  A Commodity Jurisdiction Request #012-94 was filed with the
        !            42:  * USA State Department, who handed it to the Commerce department.  The
        !            43:  * code was determined to fall under General License GTDA under ECCN 5D96G,
        !            44:  * and hence exportable.  The cryptographic interfaces were re-added by Eric
        !            45:  * Young, and then KTH proceeded to maintain the code in the free world.
        !            46:  *
        !            47:  */
        !            48:
        !            49: /*
        !            50:  * Copyright (C) 1990 by the Massachusetts Institute of Technology
        !            51:  *
        !            52:  * Export of this software from the United States of America is assumed
        !            53:  * to require a specific license from the United States Government.
        !            54:  * It is the responsibility of any person or organization contemplating
        !            55:  * export to obtain such a license before exporting.
        !            56:  *
        !            57:  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
        !            58:  * distribute this software and its documentation for any purpose and
        !            59:  * without fee is hereby granted, provided that the above copyright
        !            60:  * notice appear in all copies and that both that copyright notice and
        !            61:  * this permission notice appear in supporting documentation, and that
        !            62:  * the name of M.I.T. not be used in advertising or publicity pertaining
        !            63:  * to distribution of the software without specific, written prior
        !            64:  * permission.  M.I.T. makes no representations about the suitability of
        !            65:  * this software for any purpose.  It is provided "as is" without express
        !            66:  * or implied warranty.
        !            67:  */
        !            68:
        !            69: /* "$KTH: auth.c,v 1.23 2000/01/18 03:09:34 assar Exp $" */
        !            70:
        !            71: #if    defined(AUTHENTICATION)
        !            72: #include <stdio.h>
        !            73: #include <sys/types.h>
        !            74: #include <unistd.h>
        !            75: #include <signal.h>
        !            76: #define        AUTH_NAMES
        !            77: #include <arpa/telnet.h>
        !            78: #include <stdlib.h>
        !            79: #include <string.h>
        !            80:
        !            81: #include "encrypt.h"
        !            82: #include "auth.h"
        !            83: #include "misc-proto.h"
        !            84: #include "auth-proto.h"
        !            85:
        !            86: #define        typemask(x)             (1<<((x)-1))
        !            87:
        !            88: #ifdef KRB4_ENCPWD
        !            89: extern krb4encpwd_init();
        !            90: extern krb4encpwd_send();
        !            91: extern krb4encpwd_is();
        !            92: extern krb4encpwd_reply();
        !            93: extern krb4encpwd_status();
        !            94: extern krb4encpwd_printsub();
        !            95: #endif
        !            96:
        !            97: #ifdef RSA_ENCPWD
        !            98: extern rsaencpwd_init();
        !            99: extern rsaencpwd_send();
        !           100: extern rsaencpwd_is();
        !           101: extern rsaencpwd_reply();
        !           102: extern rsaencpwd_status();
        !           103: extern rsaencpwd_printsub();
        !           104: #endif
        !           105:
        !           106: int auth_debug_mode = 0;
        !           107: int auth_has_failed  = 0;
        !           108: int auth_enable_encrypt = 0;
        !           109: static         const   char    *Name = "Noname";
        !           110: static int     Server = 0;
        !           111: static Authenticator   *authenticated = 0;
        !           112: static int     authenticating = 0;
        !           113: static int     validuser = 0;
        !           114: static unsigned char   _auth_send_data[256];
        !           115: static unsigned char   *auth_send_data;
        !           116: static int     auth_send_cnt = 0;
        !           117:
        !           118: /*
        !           119:  * Authentication types supported.  Plese note that these are stored
        !           120:  * in priority order, i.e. try the first one first.
        !           121:  */
        !           122: Authenticator authenticators[] = {
        !           123: #ifdef UNSAFE
        !           124:     { AUTHTYPE_UNSAFE, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
        !           125:       unsafe_init,
        !           126:       unsafe_send,
        !           127:       unsafe_is,
        !           128:       unsafe_reply,
        !           129:       unsafe_status,
        !           130:       unsafe_printsub },
        !           131: #endif
        !           132: #ifdef SRA
        !           133:     { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
        !           134:       sra_init,
        !           135:       sra_send,
        !           136:       sra_is,
        !           137:       sra_reply,
        !           138:       sra_status,
        !           139:       sra_printsub },
        !           140: #endif
        !           141: #ifdef SPX
        !           142:     { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
        !           143:       spx_init,
        !           144:       spx_send,
        !           145:       spx_is,
        !           146:       spx_reply,
        !           147:       spx_status,
        !           148:       spx_printsub },
        !           149:     { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
        !           150:       spx_init,
        !           151:       spx_send,
        !           152:       spx_is,
        !           153:       spx_reply,
        !           154:       spx_status,
        !           155:       spx_printsub },
        !           156: #endif
        !           157: #ifdef KRB5
        !           158:     { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
        !           159:       kerberos5_init,
        !           160:       kerberos5_send_mutual,
        !           161:       kerberos5_is,
        !           162:       kerberos5_reply,
        !           163:       kerberos5_status,
        !           164:       kerberos5_printsub },
        !           165:     { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
        !           166:       kerberos5_init,
        !           167:       kerberos5_send_oneway,
        !           168:       kerberos5_is,
        !           169:       kerberos5_reply,
        !           170:       kerberos5_status,
        !           171:       kerberos5_printsub },
        !           172: #endif
        !           173: #ifdef KRB4
        !           174:     { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
        !           175:       kerberos4_init,
        !           176:       kerberos4_send_mutual,
        !           177:       kerberos4_is,
        !           178:       kerberos4_reply,
        !           179:       kerberos4_status,
        !           180:       kerberos4_printsub },
        !           181:     { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
        !           182:       kerberos4_init,
        !           183:       kerberos4_send_oneway,
        !           184:       kerberos4_is,
        !           185:       kerberos4_reply,
        !           186:       kerberos4_status,
        !           187:       kerberos4_printsub },
        !           188: #endif
        !           189: #ifdef KRB4_ENCPWD
        !           190:     { AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
        !           191:       krb4encpwd_init,
        !           192:       krb4encpwd_send,
        !           193:       krb4encpwd_is,
        !           194:       krb4encpwd_reply,
        !           195:       krb4encpwd_status,
        !           196:       krb4encpwd_printsub },
        !           197: #endif
        !           198: #ifdef RSA_ENCPWD
        !           199:     { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
        !           200:       rsaencpwd_init,
        !           201:       rsaencpwd_send,
        !           202:       rsaencpwd_is,
        !           203:       rsaencpwd_reply,
        !           204:       rsaencpwd_status,
        !           205:       rsaencpwd_printsub },
        !           206: #endif
        !           207:     { 0, },
        !           208: };
        !           209:
        !           210: static Authenticator NoAuth = { 0 };
        !           211:
        !           212: static int     i_support = 0;
        !           213: static int     i_wont_support = 0;
        !           214:
        !           215: Authenticator *
        !           216: findauthenticator(int type, int way)
        !           217: {
        !           218:     Authenticator *ap = authenticators;
        !           219:
        !           220:     while (ap->type && (ap->type != type || ap->way != way))
        !           221:        ++ap;
        !           222:     return(ap->type ? ap : 0);
        !           223: }
        !           224:
        !           225: void
        !           226: auth_init(const char *name, int server)
        !           227: {
        !           228:     Authenticator *ap = authenticators;
        !           229:
        !           230:     Server = server;
        !           231:     Name = name;
        !           232:
        !           233:     i_support = 0;
        !           234:     authenticated = 0;
        !           235:     authenticating = 0;
        !           236:     while (ap->type) {
        !           237:        if (!ap->init || (*ap->init)(ap, server)) {
        !           238:            i_support |= typemask(ap->type);
        !           239:            if (auth_debug_mode)
        !           240:                printf(">>>%s: I support auth type %d %d\r\n",
        !           241:                       Name,
        !           242:                       ap->type, ap->way);
        !           243:        }
        !           244:        else if (auth_debug_mode)
        !           245:            printf(">>>%s: Init failed: auth type %d %d\r\n",
        !           246:                   Name, ap->type, ap->way);
        !           247:        ++ap;
        !           248:     }
        !           249: }
        !           250:
        !           251: void
        !           252: auth_disable_name(char *name)
        !           253: {
        !           254:     int x;
        !           255:     for (x = 0; x < AUTHTYPE_CNT; ++x) {
        !           256:        if (!strcasecmp(name, AUTHTYPE_NAME(x))) {
        !           257:            i_wont_support |= typemask(x);
        !           258:            break;
        !           259:        }
        !           260:     }
        !           261: }
        !           262:
        !           263: int
        !           264: getauthmask(char *type, int *maskp)
        !           265: {
        !           266:     int x;
        !           267:
        !           268:     if (!strcasecmp(type, AUTHTYPE_NAME(0))) {
        !           269:        *maskp = -1;
        !           270:        return(1);
        !           271:     }
        !           272:
        !           273:     for (x = 1; x < AUTHTYPE_CNT; ++x) {
        !           274:        if (!strcasecmp(type, AUTHTYPE_NAME(x))) {
        !           275:            *maskp = typemask(x);
        !           276:            return(1);
        !           277:        }
        !           278:     }
        !           279:     return(0);
        !           280: }
        !           281:
        !           282: int
        !           283: auth_enable(char *type)
        !           284: {
        !           285:     return(auth_onoff(type, 1));
        !           286: }
        !           287:
        !           288: int
        !           289: auth_disable(char *type)
        !           290: {
        !           291:     return(auth_onoff(type, 0));
        !           292: }
        !           293:
        !           294: int
        !           295: auth_onoff(char *type, int on)
        !           296: {
        !           297:     int i, mask = -1;
        !           298:     Authenticator *ap;
        !           299:
        !           300:     if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
        !           301:        printf("auth %s 'type'\n", on ? "enable" : "disable");
        !           302:        printf("Where 'type' is one of:\n");
        !           303:        printf("\t%s\n", AUTHTYPE_NAME(0));
        !           304:        mask = 0;
        !           305:        for (ap = authenticators; ap->type; ap++) {
        !           306:            if ((mask & (i = typemask(ap->type))) != 0)
        !           307:                continue;
        !           308:            mask |= i;
        !           309:            printf("\t%s\n", AUTHTYPE_NAME(ap->type));
        !           310:        }
        !           311:        return(0);
        !           312:     }
        !           313:
        !           314:     if (!getauthmask(type, &mask)) {
        !           315:        printf("%s: invalid authentication type\n", type);
        !           316:        return(0);
        !           317:     }
        !           318:     if (on)
        !           319:        i_wont_support &= ~mask;
        !           320:     else
        !           321:        i_wont_support |= mask;
        !           322:     return(1);
        !           323: }
        !           324:
        !           325: int
        !           326: auth_togdebug(int on)
        !           327: {
        !           328:     if (on < 0)
        !           329:        auth_debug_mode ^= 1;
        !           330:     else
        !           331:        auth_debug_mode = on;
        !           332:     printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
        !           333:     return(1);
        !           334: }
        !           335:
        !           336: int
        !           337: auth_status(void)
        !           338: {
        !           339:     Authenticator *ap;
        !           340:     int i, mask;
        !           341:
        !           342:     if (i_wont_support == -1)
        !           343:        printf("Authentication disabled\n");
        !           344:     else
        !           345:        printf("Authentication enabled\n");
        !           346:
        !           347:     mask = 0;
        !           348:     for (ap = authenticators; ap->type; ap++) {
        !           349:        if ((mask & (i = typemask(ap->type))) != 0)
        !           350:            continue;
        !           351:        mask |= i;
        !           352:        printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
        !           353:               (i_wont_support & typemask(ap->type)) ?
        !           354:               "disabled" : "enabled");
        !           355:     }
        !           356:     return(1);
        !           357: }
        !           358:
        !           359: /*
        !           360:  * This routine is called by the server to start authentication
        !           361:  * negotiation.
        !           362:  */
        !           363: void
        !           364: auth_request(void)
        !           365: {
        !           366:     static unsigned char str_request[64] = { IAC, SB,
        !           367:                                             TELOPT_AUTHENTICATION,
        !           368:                                             TELQUAL_SEND, };
        !           369:     Authenticator *ap = authenticators;
        !           370:     unsigned char *e = str_request + 4;
        !           371:
        !           372:     if (!authenticating) {
        !           373:        authenticating = 1;
        !           374:        while (ap->type) {
        !           375:            if (i_support & ~i_wont_support & typemask(ap->type)) {
        !           376:                if (auth_debug_mode) {
        !           377:                    printf(">>>%s: Sending type %d %d\r\n",
        !           378:                           Name, ap->type, ap->way);
        !           379:                }
        !           380:                *e++ = ap->type;
        !           381:                *e++ = ap->way;
        !           382:            }
        !           383:            ++ap;
        !           384:        }
        !           385:        *e++ = IAC;
        !           386:        *e++ = SE;
        !           387:        telnet_net_write(str_request, e - str_request);
        !           388:        printsub('>', &str_request[2], e - str_request - 2);
        !           389:     }
        !           390: }
        !           391:
        !           392: /*
        !           393:  * This is called when an AUTH SEND is received.
        !           394:  * It should never arrive on the server side (as only the server can
        !           395:  * send an AUTH SEND).
        !           396:  * You should probably respond to it if you can...
        !           397:  *
        !           398:  * If you want to respond to the types out of order (i.e. even
        !           399:  * if he sends  LOGIN KERBEROS and you support both, you respond
        !           400:  * with KERBEROS instead of LOGIN (which is against what the
        !           401:  * protocol says)) you will have to hack this code...
        !           402:  */
        !           403: void
        !           404: auth_send(unsigned char *data, int cnt)
        !           405: {
        !           406:     Authenticator *ap;
        !           407:     static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
        !           408:                                        TELQUAL_IS, AUTHTYPE_NULL, 0,
        !           409:                                        IAC, SE };
        !           410:     if (Server) {
        !           411:        if (auth_debug_mode) {
        !           412:            printf(">>>%s: auth_send called!\r\n", Name);
        !           413:        }
        !           414:        return;
        !           415:     }
        !           416:
        !           417:     if (auth_debug_mode) {
        !           418:        printf(">>>%s: auth_send got:", Name);
        !           419:        printd(data, cnt); printf("\r\n");
        !           420:     }
        !           421:
        !           422:     /*
        !           423:      * Save the data, if it is new, so that we can continue looking
        !           424:      * at it if the authorization we try doesn't work
        !           425:      */
        !           426:     if (data < _auth_send_data ||
        !           427:        data > _auth_send_data + sizeof(_auth_send_data)) {
        !           428:        auth_send_cnt = cnt > sizeof(_auth_send_data)
        !           429:            ? sizeof(_auth_send_data)
        !           430:            : cnt;
        !           431:        memmove(_auth_send_data, data, auth_send_cnt);
        !           432:        auth_send_data = _auth_send_data;
        !           433:     } else {
        !           434:        /*
        !           435:         * This is probably a no-op, but we just make sure
        !           436:         */
        !           437:        auth_send_data = data;
        !           438:        auth_send_cnt = cnt;
        !           439:     }
        !           440:     while ((auth_send_cnt -= 2) >= 0) {
        !           441:        if (auth_debug_mode)
        !           442:            printf(">>>%s: He supports %d\r\n",
        !           443:                   Name, *auth_send_data);
        !           444:        if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
        !           445:            ap = findauthenticator(auth_send_data[0],
        !           446:                                   auth_send_data[1]);
        !           447:            if (ap && ap->send) {
        !           448:                if (auth_debug_mode)
        !           449:                    printf(">>>%s: Trying %d %d\r\n",
        !           450:                           Name, auth_send_data[0],
        !           451:                           auth_send_data[1]);
        !           452:                if ((*ap->send)(ap)) {
        !           453:                    /*
        !           454:                     * Okay, we found one we like
        !           455:                     * and did it.
        !           456:                     * we can go home now.
        !           457:                     */
        !           458:                    if (auth_debug_mode)
        !           459:                        printf(">>>%s: Using type %d\r\n",
        !           460:                               Name, *auth_send_data);
        !           461:                    auth_send_data += 2;
        !           462:                    return;
        !           463:                }
        !           464:            }
        !           465:            /* else
        !           466:             *  just continue on and look for the
        !           467:             *  next one if we didn't do anything.
        !           468:             */
        !           469:        }
        !           470:        auth_send_data += 2;
        !           471:     }
        !           472:     telnet_net_write(str_none, sizeof(str_none));
        !           473:     printsub('>', &str_none[2], sizeof(str_none) - 2);
        !           474:     if (auth_debug_mode)
        !           475:        printf(">>>%s: Sent failure message\r\n", Name);
        !           476:     auth_finished(0, AUTH_REJECT);
        !           477:     auth_has_failed = 1;
        !           478: #ifdef KANNAN
        !           479:     /*
        !           480:      *  We requested strong authentication, however no mechanisms worked.
        !           481:      *  Therefore, exit on client end.
        !           482:      */
        !           483:     printf("Unable to securely authenticate user ... exit\n");
        !           484:     exit(0);
        !           485: #endif /* KANNAN */
        !           486: }
        !           487:
        !           488: void
        !           489: auth_send_retry(void)
        !           490: {
        !           491:     /*
        !           492:      * if auth_send_cnt <= 0 then auth_send will end up rejecting
        !           493:      * the authentication and informing the other side of this.
        !           494:         */
        !           495:     auth_send(auth_send_data, auth_send_cnt);
        !           496: }
        !           497:
        !           498: void
        !           499: auth_is(unsigned char *data, int cnt)
        !           500: {
        !           501:     Authenticator *ap;
        !           502:
        !           503:     if (cnt < 2)
        !           504:        return;
        !           505:
        !           506:     if (data[0] == AUTHTYPE_NULL) {
        !           507:        auth_finished(0, AUTH_REJECT);
        !           508:        return;
        !           509:     }
        !           510:
        !           511:     if ((ap = findauthenticator(data[0], data[1]))) {
        !           512:        if (ap->is)
        !           513:            (*ap->is)(ap, data+2, cnt-2);
        !           514:     } else if (auth_debug_mode)
        !           515:        printf(">>>%s: Invalid authentication in IS: %d\r\n",
        !           516:               Name, *data);
        !           517: }
        !           518:
        !           519: void
        !           520: auth_reply(unsigned char *data, int cnt)
        !           521: {
        !           522:     Authenticator *ap;
        !           523:
        !           524:     if (cnt < 2)
        !           525:        return;
        !           526:
        !           527:     if ((ap = findauthenticator(data[0], data[1]))) {
        !           528:        if (ap->reply)
        !           529:            (*ap->reply)(ap, data+2, cnt-2);
        !           530:     } else if (auth_debug_mode)
        !           531:        printf(">>>%s: Invalid authentication in SEND: %d\r\n",
        !           532:               Name, *data);
        !           533: }
        !           534:
        !           535: void
        !           536: auth_name(unsigned char *data, int cnt)
        !           537: {
        !           538:     char savename[256];
        !           539:
        !           540:     if (cnt < 1) {
        !           541:        if (auth_debug_mode)
        !           542:            printf(">>>%s: Empty name in NAME\r\n", Name);
        !           543:        return;
        !           544:     }
        !           545:     if (cnt > sizeof(savename) - 1) {
        !           546:        if (auth_debug_mode)
        !           547:            printf(">>>%s: Name in NAME (%d) exceeds %lu length\r\n",
        !           548:                   Name, cnt, (unsigned long)(sizeof(savename)-1));
        !           549:        return;
        !           550:     }
        !           551:     memmove(savename, data, cnt);
        !           552:     savename[cnt] = '\0';      /* Null terminate */
        !           553:     if (auth_debug_mode)
        !           554:        printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
        !           555:     auth_encrypt_user(savename);
        !           556: }
        !           557:
        !           558: int
        !           559: auth_sendname(unsigned char *cp, int len)
        !           560: {
        !           561:     static unsigned char str_request[256+6]
        !           562:        = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
        !           563:     unsigned char *e = str_request + 4;
        !           564:     unsigned char *ee = &str_request[sizeof(str_request)-2];
        !           565:
        !           566:     while (--len >= 0) {
        !           567:        if ((*e++ = *cp++) == IAC)
        !           568:            *e++ = IAC;
        !           569:        if (e >= ee)
        !           570:            return(0);
        !           571:     }
        !           572:     *e++ = IAC;
        !           573:     *e++ = SE;
        !           574:     telnet_net_write(str_request, e - str_request);
        !           575:     printsub('>', &str_request[2], e - &str_request[2]);
        !           576:     return(1);
        !           577: }
        !           578:
        !           579: void
        !           580: auth_finished(Authenticator *ap, int result)
        !           581: {
        !           582:     if (!(authenticated = ap))
        !           583:        authenticated = &NoAuth;
        !           584:     validuser = result;
        !           585: }
        !           586:
        !           587: /* ARGSUSED */
        !           588: static void
        !           589: auth_intr(int sig)
        !           590: {
        !           591:     auth_finished(0, AUTH_REJECT);
        !           592: }
        !           593:
        !           594: int
        !           595: auth_wait(char *name, size_t name_sz)
        !           596: {
        !           597:     if (auth_debug_mode)
        !           598:        printf(">>>%s: in auth_wait.\r\n", Name);
        !           599:
        !           600:     if (Server && !authenticating)
        !           601:        return(0);
        !           602:
        !           603:     signal(SIGALRM, auth_intr);
        !           604:     alarm(30);
        !           605:     while (!authenticated)
        !           606:        if (telnet_spin())
        !           607:            break;
        !           608:     alarm(0);
        !           609:     signal(SIGALRM, SIG_DFL);
        !           610:
        !           611:     /*
        !           612:      * Now check to see if the user is valid or not
        !           613:      */
        !           614:     if (!authenticated || authenticated == &NoAuth)
        !           615:        return(AUTH_REJECT);
        !           616:
        !           617:     if (validuser == AUTH_VALID)
        !           618:        validuser = AUTH_USER;
        !           619:
        !           620:     if (authenticated->status)
        !           621:        validuser = (*authenticated->status)(authenticated,
        !           622:                                             name, name_sz,
        !           623:                                             validuser);
        !           624:     return(validuser);
        !           625: }
        !           626:
        !           627: void
        !           628: auth_debug(int mode)
        !           629: {
        !           630:     auth_debug_mode = mode;
        !           631: }
        !           632:
        !           633: void
        !           634: auth_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
        !           635: {
        !           636:     Authenticator *ap;
        !           637:
        !           638:     if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
        !           639:        (*ap->printsub)(data, cnt, buf, buflen);
        !           640:     else
        !           641:        auth_gen_printsub(data, cnt, buf, buflen);
        !           642: }
        !           643:
        !           644: void
        !           645: auth_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
        !           646: {
        !           647:     unsigned char *cp;
        !           648:     unsigned char tbuf[16];
        !           649:
        !           650:     cnt -= 3;
        !           651:     data += 3;
        !           652:     buf[buflen-1] = '\0';
        !           653:     buf[buflen-2] = '*';
        !           654:     buflen -= 2;
        !           655:     for (; cnt > 0; cnt--, data++) {
        !           656:        snprintf(tbuf, sizeof(tbuf), " %d", *data);
        !           657:        for (cp = tbuf; *cp && buflen > 0; --buflen)
        !           658:            *buf++ = *cp++;
        !           659:        if (buflen <= 0)
        !           660:            return;
        !           661:     }
        !           662:     *buf = '\0';
        !           663: }
        !           664: #endif