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

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

1.1     ! deraadt     1: /*     $OpenBSD: kerberos5.c,v 1.2 2003/06/02 19:38:25 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: /*
        !            33:  * This source code is no longer held under any constraint of USA
        !            34:  * `cryptographic laws' since it was exported legally.  The cryptographic
        !            35:  * functions were removed from the code and a "Bones" distribution was
        !            36:  * made.  A Commodity Jurisdiction Request #012-94 was filed with the
        !            37:  * USA State Department, who handed it to the Commerce department.  The
        !            38:  * code was determined to fall under General License GTDA under ECCN 5D96G,
        !            39:  * and hence exportable.  The cryptographic interfaces were re-added by Eric
        !            40:  * Young, and then KTH proceeded to maintain the code in the free world.
        !            41:  *
        !            42:  */
        !            43:
        !            44: /*
        !            45:  * Copyright (C) 1990 by the Massachusetts Institute of Technology
        !            46:  *
        !            47:  * Export of this software from the United States of America may
        !            48:  * require a specific license from the United States Government.
        !            49:  * It is the responsibility of any person or organization contemplating
        !            50:  * export to obtain such a license before exporting.
        !            51:  *
        !            52:  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
        !            53:  * distribute this software and its documentation for any purpose and
        !            54:  * without fee is hereby granted, provided that the above copyright
        !            55:  * notice appear in all copies and that both that copyright notice and
        !            56:  * this permission notice appear in supporting documentation, and that
        !            57:  * the name of M.I.T. not be used in advertising or publicity pertaining
        !            58:  * to distribution of the software without specific, written prior
        !            59:  * permission.  M.I.T. makes no representations about the suitability of
        !            60:  * this software for any purpose.  It is provided "as is" without express
        !            61:  * or implied warranty.
        !            62:  */
        !            63:
        !            64: /* $KTH: kerberos5.c,v 1.47 2001/01/09 18:45:33 assar Exp $ */
        !            65:
        !            66: #ifdef KRB5
        !            67:
        !            68: #include <arpa/telnet.h>
        !            69: #include <stdio.h>
        !            70: #include <stdlib.h>
        !            71: #include <string.h>
        !            72: #include <unistd.h>
        !            73: #include <netdb.h>
        !            74: #include <ctype.h>
        !            75: #include <pwd.h>
        !            76: #include <errno.h>
        !            77: #define Authenticator k5_Authenticator
        !            78: #include <kerberosV/krb5.h>
        !            79: #undef Authenticator
        !            80: #include <err.h>
        !            81:
        !            82: #include "encrypt.h"
        !            83: #include "auth.h"
        !            84: #include "misc.h"
        !            85:
        !            86: #if defined(DCE)
        !            87: int dfsk5ok = 0;
        !            88: int dfspag = 0;
        !            89: int dfsfwd = 0;
        !            90: #endif
        !            91:
        !            92: int forward_flags = 0;  /* Flags get set in telnet/main.c on -f and -F */
        !            93:
        !            94: int forward(int);
        !            95: int forwardable(int);
        !            96:
        !            97: /* These values need to be the same as those defined in telnet/main.c. */
        !            98: /* Either define them in both places, or put in some common header file. */
        !            99: #define OPTS_FORWARD_CREDS     0x00000002
        !           100: #define OPTS_FORWARDABLE_CREDS 0x00000001
        !           101:
        !           102:
        !           103: void kerberos5_forward (Authenticator *);
        !           104:
        !           105: static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
        !           106:                                        AUTHTYPE_KERBEROS_V5, };
        !           107:
        !           108: #define        KRB_AUTH                0       /* Authentication data follows */
        !           109: #define        KRB_REJECT              1       /* Rejected (reason might follow) */
        !           110: #define        KRB_ACCEPT              2       /* Accepted */
        !           111: #define        KRB_RESPONSE            3       /* Response for mutual auth. */
        !           112:
        !           113: #define KRB_FORWARD            4       /* Forwarded credentials follow */
        !           114: #define KRB_FORWARD_ACCEPT             5       /* Forwarded credentials accepted */
        !           115: #define KRB_FORWARD_REJECT             6       /* Forwarded credentials rejected */
        !           116:
        !           117: static krb5_data auth;
        !           118: static  krb5_ticket *ticket;
        !           119:
        !           120: static krb5_context context;
        !           121: static krb5_auth_context auth_context;
        !           122:
        !           123: int
        !           124: check_krb5_tickets()
        !           125: {
        !           126:     krb5_error_code ret;
        !           127:     krb5_context context;
        !           128:     krb5_ccache ccache;
        !           129:     krb5_principal principal;
        !           130:     int retval = 1;
        !           131:
        !           132:     ret = krb5_init_context(&context);
        !           133:     if(ret)
        !           134:        errx(1, "krb5_init_context failt: %d", ret);
        !           135:
        !           136:     ret = krb5_cc_default(context, &ccache);
        !           137:     if(ret)
        !           138:        errx(1, "krb5_cc_default: %d", ret);
        !           139:
        !           140:     ret = krb5_cc_get_principal (context, ccache, &principal);
        !           141:     switch(ret) {
        !           142:     case ENOENT:
        !           143:        retval = 0;
        !           144:        goto done;
        !           145:     case 0:
        !           146:        retval = 1;
        !           147:        goto done;
        !           148:     default:
        !           149:        errx(1, "krb5_cc_get_principal: %d", ret);
        !           150:        break;
        !           151:     }
        !           152:
        !           153:  done:
        !           154:     krb5_free_context(context);
        !           155:     return retval;
        !           156: }
        !           157:
        !           158: static int
        !           159: Data(Authenticator *ap, int type, void *d, int c)
        !           160: {
        !           161:     unsigned char *p = str_data + 4;
        !           162:     unsigned char *cd = (unsigned char *)d;
        !           163:
        !           164:     if (c == -1)
        !           165:        c = strlen(cd);
        !           166:
        !           167:     if (auth_debug_mode) {
        !           168:        printf("%s:%d: [%d] (%d)",
        !           169:               str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
        !           170:               str_data[3],
        !           171:               type, c);
        !           172:        printd(d, c);
        !           173:        printf("\r\n");
        !           174:     }
        !           175:     *p++ = ap->type;
        !           176:     *p++ = ap->way;
        !           177:     *p++ = type;
        !           178:     while (c-- > 0) {
        !           179:        if ((*p++ = *cd++) == IAC)
        !           180:            *p++ = IAC;
        !           181:     }
        !           182:     *p++ = IAC;
        !           183:     *p++ = SE;
        !           184:     if (str_data[3] == TELQUAL_IS)
        !           185:        printsub('>', &str_data[2], p - &str_data[2]);
        !           186:     return(telnet_net_write(str_data, p - str_data));
        !           187: }
        !           188:
        !           189: int
        !           190: kerberos5_init(Authenticator *ap, int server)
        !           191: {
        !           192:     krb5_error_code ret;
        !           193:
        !           194:     ret = krb5_init_context(&context);
        !           195:     if (ret)
        !           196:        return 0;
        !           197:     if (server) {
        !           198:        krb5_keytab kt;
        !           199:        krb5_kt_cursor cursor;
        !           200:
        !           201:        ret = krb5_kt_default(context, &kt);
        !           202:        if (ret)
        !           203:            return 0;
        !           204:
        !           205:        ret = krb5_kt_start_seq_get (context, kt, &cursor);
        !           206:        if (ret) {
        !           207:            krb5_kt_close (context, kt);
        !           208:            return 0;
        !           209:        }
        !           210:        krb5_kt_end_seq_get (context, kt, &cursor);
        !           211:        krb5_kt_close (context, kt);
        !           212:
        !           213:        str_data[3] = TELQUAL_REPLY;
        !           214:     } else
        !           215:        str_data[3] = TELQUAL_IS;
        !           216:     return(1);
        !           217: }
        !           218:
        !           219: extern int net;
        !           220: static int
        !           221: kerberos5_send(char *name, Authenticator *ap)
        !           222: {
        !           223:     krb5_error_code ret;
        !           224:     krb5_ccache ccache;
        !           225:     int ap_opts;
        !           226:     krb5_data cksum_data;
        !           227:     char foo[2];
        !           228:
        !           229:     if(check_krb5_tickets() != 1)
        !           230:        return 0;
        !           231:
        !           232:     if (!UserNameRequested) {
        !           233:        if (auth_debug_mode) {
        !           234:            printf("Kerberos V5: no user name supplied\r\n");
        !           235:        }
        !           236:        return(0);
        !           237:     }
        !           238:
        !           239:     ret = krb5_cc_default(context, &ccache);
        !           240:     if (ret) {
        !           241:        if (auth_debug_mode) {
        !           242:            printf("Kerberos V5: could not get default ccache: %s\r\n",
        !           243:                   krb5_get_err_text (context, ret));
        !           244:        }
        !           245:        return 0;
        !           246:     }
        !           247:
        !           248:     if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
        !           249:        ap_opts = AP_OPTS_MUTUAL_REQUIRED;
        !           250:     else
        !           251:        ap_opts = 0;
        !           252:
        !           253:     ap_opts |= AP_OPTS_USE_SUBKEY;
        !           254:
        !           255:     ret = krb5_auth_con_init (context, &auth_context);
        !           256:     if (ret) {
        !           257:        if (auth_debug_mode) {
        !           258:            printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
        !           259:                   krb5_get_err_text(context, ret));
        !           260:        }
        !           261:        return(0);
        !           262:     }
        !           263:
        !           264:     ret = krb5_auth_con_setaddrs_from_fd (context,
        !           265:                                          auth_context,
        !           266:                                          &net);
        !           267:     if (ret) {
        !           268:        if (auth_debug_mode) {
        !           269:            printf ("Kerberos V5:"
        !           270:                    " krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
        !           271:                    krb5_get_err_text(context, ret));
        !           272:        }
        !           273:        return(0);
        !           274:     }
        !           275:
        !           276:     krb5_auth_con_setkeytype (context, auth_context, KEYTYPE_DES);
        !           277:
        !           278:     foo[0] = ap->type;
        !           279:     foo[1] = ap->way;
        !           280:
        !           281:     cksum_data.length = sizeof(foo);
        !           282:     cksum_data.data   = foo;
        !           283:
        !           284:
        !           285:     {
        !           286:        krb5_principal service;
        !           287:        char sname[128];
        !           288:
        !           289:
        !           290:        ret = krb5_sname_to_principal (context,
        !           291:                                       RemoteHostName,
        !           292:                                       NULL,
        !           293:                                       KRB5_NT_SRV_HST,
        !           294:                                       &service);
        !           295:        if(ret) {
        !           296:            if (auth_debug_mode) {
        !           297:                printf ("Kerberos V5:"
        !           298:                        " krb5_sname_to_principal(%s) failed (%s)\r\n",
        !           299:                        RemoteHostName, krb5_get_err_text(context, ret));
        !           300:            }
        !           301:            return 0;
        !           302:        }
        !           303:        ret = krb5_unparse_name_fixed(context, service, sname, sizeof(sname));
        !           304:        if(ret) {
        !           305:            if (auth_debug_mode) {
        !           306:                printf ("Kerberos V5:"
        !           307:                        " krb5_unparse_name_fixed failed (%s)\r\n",
        !           308:                        krb5_get_err_text(context, ret));
        !           309:            }
        !           310:            return 0;
        !           311:        }
        !           312:        printf("[ Trying %s (%s)... ]\r\n", name, sname);
        !           313:        ret = krb5_mk_req_exact(context, &auth_context, ap_opts,
        !           314:                                service,
        !           315:                                &cksum_data, ccache, &auth);
        !           316:        krb5_free_principal (context, service);
        !           317:
        !           318:     }
        !           319:     if (ret) {
        !           320:        if (1 || auth_debug_mode) {
        !           321:            printf("Kerberos V5: mk_req failed (%s)\r\n",
        !           322:                   krb5_get_err_text(context, ret));
        !           323:        }
        !           324:        return(0);
        !           325:     }
        !           326:
        !           327:     if (!auth_sendname((unsigned char *)UserNameRequested,
        !           328:                       strlen(UserNameRequested))) {
        !           329:        if (auth_debug_mode)
        !           330:            printf("Not enough room for user name\r\n");
        !           331:        return(0);
        !           332:     }
        !           333:     if (!Data(ap, KRB_AUTH, auth.data, auth.length)) {
        !           334:        if (auth_debug_mode)
        !           335:            printf("Not enough room for authentication data\r\n");
        !           336:        return(0);
        !           337:     }
        !           338:     if (auth_debug_mode) {
        !           339:        printf("Sent Kerberos V5 credentials to server\r\n");
        !           340:     }
        !           341:     return(1);
        !           342: }
        !           343:
        !           344: int
        !           345: kerberos5_send_mutual(Authenticator *ap)
        !           346: {
        !           347:     return kerberos5_send("mutual KERBEROS5", ap);
        !           348: }
        !           349:
        !           350: int
        !           351: kerberos5_send_oneway(Authenticator *ap)
        !           352: {
        !           353:     return kerberos5_send("KERBEROS5", ap);
        !           354: }
        !           355:
        !           356: void
        !           357: kerberos5_is(Authenticator *ap, unsigned char *data, int cnt)
        !           358: {
        !           359:     krb5_error_code ret;
        !           360:     krb5_data outbuf;
        !           361:     krb5_keyblock *key_block;
        !           362:     char *name;
        !           363:     krb5_principal server;
        !           364:     int zero = 0;
        !           365:
        !           366:     if (cnt-- < 1)
        !           367:        return;
        !           368:     switch (*data++) {
        !           369:     case KRB_AUTH:
        !           370:        auth.data = (char *)data;
        !           371:        auth.length = cnt;
        !           372:
        !           373:        auth_context = NULL;
        !           374:
        !           375:        ret = krb5_auth_con_init (context, &auth_context);
        !           376:        if (ret) {
        !           377:            Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1);
        !           378:            auth_finished(ap, AUTH_REJECT);
        !           379:            if (auth_debug_mode)
        !           380:                printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
        !           381:                       krb5_get_err_text(context, ret));
        !           382:            return;
        !           383:        }
        !           384:
        !           385:        ret = krb5_auth_con_setaddrs_from_fd (context,
        !           386:                                              auth_context,
        !           387:                                              &zero);
        !           388:        if (ret) {
        !           389:            Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1);
        !           390:            auth_finished(ap, AUTH_REJECT);
        !           391:            if (auth_debug_mode)
        !           392:                printf("Kerberos V5: "
        !           393:                       "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
        !           394:                       krb5_get_err_text(context, ret));
        !           395:            return;
        !           396:        }
        !           397:
        !           398:        ret = krb5_sock_to_principal (context,
        !           399:                                      0,
        !           400:                                      "host",
        !           401:                                      KRB5_NT_SRV_HST,
        !           402:                                      &server);
        !           403:        if (ret) {
        !           404:            Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1);
        !           405:            auth_finished(ap, AUTH_REJECT);
        !           406:            if (auth_debug_mode)
        !           407:                printf("Kerberos V5: "
        !           408:                       "krb5_sock_to_principal failed (%s)\r\n",
        !           409:                       krb5_get_err_text(context, ret));
        !           410:            return;
        !           411:        }
        !           412:
        !           413:        ret = krb5_rd_req(context,
        !           414:                          &auth_context,
        !           415:                          &auth,
        !           416:                          server,
        !           417:                          NULL,
        !           418:                          NULL,
        !           419:                          &ticket);
        !           420:
        !           421:        krb5_free_principal (context, server);
        !           422:        if (ret) {
        !           423:            char *errbuf;
        !           424:
        !           425:            asprintf(&errbuf,
        !           426:                     "Read req failed: %s",
        !           427:                     krb5_get_err_text(context, ret));
        !           428:            Data(ap, KRB_REJECT, errbuf, -1);
        !           429:            if (auth_debug_mode)
        !           430:                printf("%s\r\n", errbuf);
        !           431:            free (errbuf);
        !           432:            return;
        !           433:        }
        !           434:
        !           435:        {
        !           436:            char foo[2];
        !           437:
        !           438:            foo[0] = ap->type;
        !           439:            foo[1] = ap->way;
        !           440:
        !           441:            ret = krb5_verify_authenticator_checksum(context,
        !           442:                                                     auth_context,
        !           443:                                                     foo,
        !           444:                                                     sizeof(foo));
        !           445:
        !           446:            if (ret) {
        !           447:                char *errbuf;
        !           448:                asprintf(&errbuf, "Bad checksum: %s",
        !           449:                         krb5_get_err_text(context, ret));
        !           450:                Data(ap, KRB_REJECT, errbuf, -1);
        !           451:                if (auth_debug_mode)
        !           452:                    printf ("%s\r\n", errbuf);
        !           453:                free(errbuf);
        !           454:                return;
        !           455:            }
        !           456:        }
        !           457:        ret = krb5_auth_con_getremotesubkey (context,
        !           458:                                             auth_context,
        !           459:                                             &key_block);
        !           460:
        !           461:        if (ret) {
        !           462:            Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1);
        !           463:            auth_finished(ap, AUTH_REJECT);
        !           464:            if (auth_debug_mode)
        !           465:                printf("Kerberos V5: "
        !           466:                       "krb5_auth_con_getremotesubkey failed (%s)\r\n",
        !           467:                       krb5_get_err_text(context, ret));
        !           468:            return;
        !           469:        }
        !           470:
        !           471:        if (key_block == NULL) {
        !           472:            ret = krb5_auth_con_getkey(context,
        !           473:                                       auth_context,
        !           474:                                       &key_block);
        !           475:        }
        !           476:        if (ret) {
        !           477:            Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1);
        !           478:            auth_finished(ap, AUTH_REJECT);
        !           479:            if (auth_debug_mode)
        !           480:                printf("Kerberos V5: "
        !           481:                       "krb5_auth_con_getkey failed (%s)\r\n",
        !           482:                       krb5_get_err_text(context, ret));
        !           483:            return;
        !           484:        }
        !           485:        if (key_block == NULL) {
        !           486:            Data(ap, KRB_REJECT, "no subkey received", -1);
        !           487:            auth_finished(ap, AUTH_REJECT);
        !           488:            if (auth_debug_mode)
        !           489:                printf("Kerberos V5: "
        !           490:                       "krb5_auth_con_getremotesubkey returned NULL key\r\n");
        !           491:            return;
        !           492:        }
        !           493:
        !           494:        if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
        !           495:            ret = krb5_mk_rep(context, auth_context, &outbuf);
        !           496:            if (ret) {
        !           497:                Data(ap, KRB_REJECT,
        !           498:                     "krb5_mk_rep failed", -1);
        !           499:                auth_finished(ap, AUTH_REJECT);
        !           500:                if (auth_debug_mode)
        !           501:                    printf("Kerberos V5: "
        !           502:                           "krb5_mk_rep failed (%s)\r\n",
        !           503:                           krb5_get_err_text(context, ret));
        !           504:                return;
        !           505:            }
        !           506:            Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
        !           507:        }
        !           508:        if (krb5_unparse_name(context, ticket->client, &name))
        !           509:            name = 0;
        !           510:
        !           511:        if(UserNameRequested && krb5_kuserok(context,
        !           512:                                             ticket->client,
        !           513:                                             UserNameRequested)) {
        !           514:            Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
        !           515:            if (auth_debug_mode) {
        !           516:                printf("Kerberos5 identifies him as ``%s''\r\n",
        !           517:                       name ? name : "");
        !           518:            }
        !           519:
        !           520:            if(key_block->keytype == ETYPE_DES_CBC_MD5 ||
        !           521:               key_block->keytype == ETYPE_DES_CBC_MD4 ||
        !           522:               key_block->keytype == ETYPE_DES_CBC_CRC) {
        !           523:                Session_Key skey;
        !           524:
        !           525:                skey.type = SK_DES;
        !           526:                skey.length = 8;
        !           527:                skey.data = key_block->keyvalue.data;
        !           528:                encrypt_session_key(&skey, 0);
        !           529:            }
        !           530:
        !           531:        } else {
        !           532:            char *msg;
        !           533:
        !           534:            asprintf (&msg, "user `%s' is not authorized to "
        !           535:                      "login as `%s'",
        !           536:                      name ? name : "<unknown>",
        !           537:                      UserNameRequested ? UserNameRequested : "<nobody>");
        !           538:            if (msg == NULL)
        !           539:                Data(ap, KRB_REJECT, NULL, 0);
        !           540:            else {
        !           541:                Data(ap, KRB_REJECT, (void *)msg, -1);
        !           542:                free(msg);
        !           543:            }
        !           544:            auth_finished (ap, AUTH_REJECT);
        !           545:            krb5_free_keyblock_contents(context, key_block);
        !           546:            break;
        !           547:        }
        !           548:        auth_finished(ap, AUTH_USER);
        !           549:        krb5_free_keyblock_contents(context, key_block);
        !           550:
        !           551:        break;
        !           552:     case KRB_FORWARD: {
        !           553:        struct passwd *pwd;
        !           554:        char ccname[1024];      /* XXX */
        !           555:        krb5_data inbuf;
        !           556:        krb5_ccache ccache;
        !           557:        inbuf.data = (char *)data;
        !           558:        inbuf.length = cnt;
        !           559:
        !           560:        pwd = getpwnam (UserNameRequested);
        !           561:        if (pwd == NULL)
        !           562:            break;
        !           563:
        !           564:        snprintf (ccname, sizeof(ccname),
        !           565:                  "FILE:/tmp/krb5cc_%u", pwd->pw_uid);
        !           566:
        !           567:        ret = krb5_cc_resolve (context, ccname, &ccache);
        !           568:        if (ret) {
        !           569:            if (auth_debug_mode)
        !           570:                printf ("Kerberos V5: could not get ccache: %s\r\n",
        !           571:                        krb5_get_err_text(context, ret));
        !           572:            break;
        !           573:        }
        !           574:
        !           575:        ret = krb5_cc_initialize (context,
        !           576:                                  ccache,
        !           577:                                  ticket->client);
        !           578:        if (ret) {
        !           579:            if (auth_debug_mode)
        !           580:                printf ("Kerberos V5: could not init ccache: %s\r\n",
        !           581:                        krb5_get_err_text(context, ret));
        !           582:            break;
        !           583:        }
        !           584:
        !           585: #if defined(DCE)
        !           586:        esetenv("KRB5CCNAME", ccname, 1);
        !           587: #endif
        !           588:        ret = krb5_rd_cred2 (context,
        !           589:                             auth_context,
        !           590:                             ccache,
        !           591:                             &inbuf);
        !           592:        if(ret) {
        !           593:            char *errbuf;
        !           594:
        !           595:            asprintf (&errbuf,
        !           596:                      "Read forwarded creds failed: %s",
        !           597:                      krb5_get_err_text (context, ret));
        !           598:            if(errbuf == NULL)
        !           599:                Data(ap, KRB_FORWARD_REJECT, NULL, 0);
        !           600:            else
        !           601:                Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
        !           602:            if (auth_debug_mode)
        !           603:                printf("Could not read forwarded credentials: %s\r\n",
        !           604:                       errbuf);
        !           605:            free (errbuf);
        !           606:        } else {
        !           607:            Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
        !           608: #if defined(DCE)
        !           609:            dfsfwd = 1;
        !           610: #endif
        !           611:        }
        !           612:        chown (ccname + 5, pwd->pw_uid, -1);
        !           613:        if (auth_debug_mode)
        !           614:            printf("Forwarded credentials obtained\r\n");
        !           615:        break;
        !           616:     }
        !           617:     default:
        !           618:        if (auth_debug_mode)
        !           619:            printf("Unknown Kerberos option %d\r\n", data[-1]);
        !           620:        Data(ap, KRB_REJECT, 0, 0);
        !           621:        break;
        !           622:     }
        !           623: }
        !           624:
        !           625: void
        !           626: kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt)
        !           627: {
        !           628:     static int mutual_complete = 0;
        !           629:
        !           630:     if (cnt-- < 1)
        !           631:        return;
        !           632:     switch (*data++) {
        !           633:     case KRB_REJECT:
        !           634:        if (cnt > 0) {
        !           635:            printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n",
        !           636:                   cnt, data);
        !           637:        } else
        !           638:            printf("[ Kerberos V5 refuses authentication ]\r\n");
        !           639:        auth_send_retry();
        !           640:        return;
        !           641:     case KRB_ACCEPT: {
        !           642:        krb5_error_code ret;
        !           643:        Session_Key skey;
        !           644:        krb5_keyblock *keyblock;
        !           645:
        !           646:        if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
        !           647:            !mutual_complete) {
        !           648:            printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n");
        !           649:            auth_send_retry();
        !           650:            return;
        !           651:        }
        !           652:        if (cnt)
        !           653:            printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data);
        !           654:        else
        !           655:            printf("[ Kerberos V5 accepts you ]\r\n");
        !           656:
        !           657:        ret = krb5_auth_con_getlocalsubkey (context,
        !           658:                                            auth_context,
        !           659:                                            &keyblock);
        !           660:        if (ret)
        !           661:            ret = krb5_auth_con_getkey (context,
        !           662:                                        auth_context,
        !           663:                                        &keyblock);
        !           664:        if(ret) {
        !           665:            printf("[ krb5_auth_con_getkey: %s ]\r\n",
        !           666:                   krb5_get_err_text(context, ret));
        !           667:            auth_send_retry();
        !           668:            return;
        !           669:        }
        !           670:
        !           671:        skey.type = SK_DES;
        !           672:        skey.length = 8;
        !           673:        skey.data = keyblock->keyvalue.data;
        !           674:        encrypt_session_key(&skey, 0);
        !           675:        krb5_free_keyblock_contents (context, keyblock);
        !           676:        auth_finished(ap, AUTH_USER);
        !           677:        if (forward_flags & OPTS_FORWARD_CREDS)
        !           678:            kerberos5_forward(ap);
        !           679:        break;
        !           680:     }
        !           681:     case KRB_RESPONSE:
        !           682:        if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
        !           683:            /* the rest of the reply should contain a krb_ap_rep */
        !           684:          krb5_ap_rep_enc_part *reply;
        !           685:          krb5_data inbuf;
        !           686:          krb5_error_code ret;
        !           687:
        !           688:          inbuf.length = cnt;
        !           689:          inbuf.data = (char *)data;
        !           690:
        !           691:          ret = krb5_rd_rep(context, auth_context, &inbuf, &reply);
        !           692:          if (ret) {
        !           693:              printf("[ Mutual authentication failed: %s ]\r\n",
        !           694:                     krb5_get_err_text (context, ret));
        !           695:              auth_send_retry();
        !           696:              return;
        !           697:          }
        !           698:          krb5_free_ap_rep_enc_part(context, reply);
        !           699:          mutual_complete = 1;
        !           700:        }
        !           701:        return;
        !           702:     case KRB_FORWARD_ACCEPT:
        !           703:        printf("[ Kerberos V5 accepted forwarded credentials ]\r\n");
        !           704:        return;
        !           705:     case KRB_FORWARD_REJECT:
        !           706:        printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n",
        !           707:               cnt, data);
        !           708:        return;
        !           709:     default:
        !           710:        if (auth_debug_mode)
        !           711:            printf("Unknown Kerberos option %d\r\n", data[-1]);
        !           712:        return;
        !           713:     }
        !           714: }
        !           715:
        !           716: int
        !           717: kerberos5_status(Authenticator *ap, char *name, size_t name_sz, int level)
        !           718: {
        !           719:     if (level < AUTH_USER)
        !           720:        return(level);
        !           721:
        !           722:     if (UserNameRequested &&
        !           723:        krb5_kuserok(context,
        !           724:                     ticket->client,
        !           725:                     UserNameRequested))
        !           726:        {
        !           727:            strlcpy(name, UserNameRequested, name_sz);
        !           728: #if defined(DCE)
        !           729:            dfsk5ok = 1;
        !           730: #endif
        !           731:            return(AUTH_VALID);
        !           732:        } else
        !           733:            return(AUTH_USER);
        !           734: }
        !           735:
        !           736: #define        BUMP(buf, len)          while (*(buf)) {++(buf), --(len);}
        !           737: #define        ADDC(buf, len, c)       if ((len) > 0) {*(buf)++ = (c); --(len);}
        !           738:
        !           739: void
        !           740: kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
        !           741: {
        !           742:     int i;
        !           743:
        !           744:     buf[buflen-1] = '\0';              /* make sure its NULL terminated */
        !           745:     buflen -= 1;
        !           746:
        !           747:     switch(data[3]) {
        !           748:     case KRB_REJECT:           /* Rejected (reason might follow) */
        !           749:        strlcpy((char *)buf, " REJECT ", buflen);
        !           750:        goto common;
        !           751:
        !           752:     case KRB_ACCEPT:           /* Accepted (name might follow) */
        !           753:        strlcpy((char *)buf, " ACCEPT ", buflen);
        !           754:     common:
        !           755:        BUMP(buf, buflen);
        !           756:        if (cnt <= 4)
        !           757:            break;
        !           758:        ADDC(buf, buflen, '"');
        !           759:        for (i = 4; i < cnt; i++)
        !           760:            ADDC(buf, buflen, data[i]);
        !           761:        ADDC(buf, buflen, '"');
        !           762:        ADDC(buf, buflen, '\0');
        !           763:        break;
        !           764:
        !           765:
        !           766:     case KRB_AUTH:                     /* Authentication data follows */
        !           767:        strlcpy((char *)buf, " AUTH", buflen);
        !           768:        goto common2;
        !           769:
        !           770:     case KRB_RESPONSE:
        !           771:        strlcpy((char *)buf, " RESPONSE", buflen);
        !           772:        goto common2;
        !           773:
        !           774:     case KRB_FORWARD:          /* Forwarded credentials follow */
        !           775:        strlcpy((char *)buf, " FORWARD", buflen);
        !           776:        goto common2;
        !           777:
        !           778:     case KRB_FORWARD_ACCEPT:   /* Forwarded credentials accepted */
        !           779:        strlcpy((char *)buf, " FORWARD_ACCEPT", buflen);
        !           780:        goto common2;
        !           781:
        !           782:     case KRB_FORWARD_REJECT:   /* Forwarded credentials rejected */
        !           783:        /* (reason might follow) */
        !           784:        strlcpy((char *)buf, " FORWARD_REJECT", buflen);
        !           785:        goto common2;
        !           786:
        !           787:     default:
        !           788:        snprintf(buf, buflen, " %d (unknown)", data[3]);
        !           789:     common2:
        !           790:        BUMP(buf, buflen);
        !           791:        for (i = 4; i < cnt; i++) {
        !           792:            snprintf(buf, buflen, " %d", data[i]);
        !           793:            BUMP(buf, buflen);
        !           794:        }
        !           795:        break;
        !           796:     }
        !           797: }
        !           798:
        !           799: void
        !           800: kerberos5_forward(Authenticator *ap)
        !           801: {
        !           802:     krb5_error_code ret;
        !           803:     krb5_ccache     ccache;
        !           804:     krb5_creds      creds;
        !           805:     krb5_kdc_flags  flags;
        !           806:     krb5_data       out_data;
        !           807:     krb5_principal  principal;
        !           808:
        !           809:     ret = krb5_cc_default (context, &ccache);
        !           810:     if (ret) {
        !           811:        if (auth_debug_mode)
        !           812:            printf ("KerberosV5: could not get default ccache: %s\r\n",
        !           813:                    krb5_get_err_text (context, ret));
        !           814:        return;
        !           815:     }
        !           816:
        !           817:     ret = krb5_cc_get_principal (context, ccache, &principal);
        !           818:     if (ret) {
        !           819:        if (auth_debug_mode)
        !           820:            printf ("KerberosV5: could not get principal: %s\r\n",
        !           821:                    krb5_get_err_text (context, ret));
        !           822:        return;
        !           823:     }
        !           824:
        !           825:     memset (&creds, 0, sizeof(creds));
        !           826:
        !           827:     creds.client = principal;
        !           828:
        !           829:     ret = krb5_build_principal (context,
        !           830:                                &creds.server,
        !           831:                                strlen(principal->realm),
        !           832:                                principal->realm,
        !           833:                                "krbtgt",
        !           834:                                principal->realm,
        !           835:                                NULL);
        !           836:
        !           837:     if (ret) {
        !           838:        if (auth_debug_mode)
        !           839:            printf ("KerberosV5: could not get principal: %s\r\n",
        !           840:                    krb5_get_err_text (context, ret));
        !           841:        return;
        !           842:     }
        !           843:
        !           844:     creds.times.endtime = 0;
        !           845:
        !           846:     flags.i = 0;
        !           847:     flags.b.forwarded = 1;
        !           848:     if (forward_flags & OPTS_FORWARDABLE_CREDS)
        !           849:        flags.b.forwardable = 1;
        !           850:
        !           851:     ret = krb5_get_forwarded_creds (context,
        !           852:                                    auth_context,
        !           853:                                    ccache,
        !           854:                                    flags.i,
        !           855:                                    RemoteHostName,
        !           856:                                    &creds,
        !           857:                                    &out_data);
        !           858:     if (ret) {
        !           859:        if (auth_debug_mode)
        !           860:            printf ("Kerberos V5: error getting forwarded creds: %s\r\n",
        !           861:                    krb5_get_err_text (context, ret));
        !           862:        return;
        !           863:     }
        !           864:
        !           865:     if(!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) {
        !           866:        if (auth_debug_mode)
        !           867:            printf("Not enough room for authentication data\r\n");
        !           868:     } else {
        !           869:        if (auth_debug_mode)
        !           870:            printf("Forwarded local Kerberos V5 credentials to server\r\n");
        !           871:     }
        !           872: }
        !           873:
        !           874: #if defined(DCE)
        !           875: /* if this was a K5 authentication try and join a PAG for the user. */
        !           876: void
        !           877: kerberos5_dfspag(void)
        !           878: {
        !           879:     if (dfsk5ok) {
        !           880:        dfspag = krb5_dfs_pag(context, dfsfwd, ticket->client,
        !           881:                              UserNameRequested);
        !           882:     }
        !           883: }
        !           884: #endif
        !           885:
        !           886: int
        !           887: kerberos5_set_forward(int on)
        !           888: {
        !           889:     if(on == 0)
        !           890:        forward_flags &= ~OPTS_FORWARD_CREDS;
        !           891:     if(on == 1)
        !           892:        forward_flags |= OPTS_FORWARD_CREDS;
        !           893:     if(on == -1)
        !           894:        forward_flags ^= OPTS_FORWARD_CREDS;
        !           895:     return 0;
        !           896: }
        !           897:
        !           898: int
        !           899: kerberos5_set_forwardable(int on)
        !           900: {
        !           901:     if(on == 0)
        !           902:        forward_flags &= ~OPTS_FORWARDABLE_CREDS;
        !           903:     if(on == 1)
        !           904:        forward_flags |= OPTS_FORWARDABLE_CREDS;
        !           905:     if(on == -1)
        !           906:        forward_flags ^= OPTS_FORWARDABLE_CREDS;
        !           907:     return 0;
        !           908: }
        !           909:
        !           910: #endif /* KRB5 */