~ubuntu-branches/ubuntu/maverick/krb5/maverick

« back to all changes in this revision

Viewing changes to src/kdc/kerberos_v4.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman, Russ Allbery, Sam Hartman
  • Date: 2008-08-21 10:41:41 UTC
  • mfrom: (11.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080821104141-a0f9c4o4cpo8xd0o
Tags: 1.6.dfsg.4~beta1-4
[ Russ Allbery ]
* Translation updates:
  - Swedish, thanks Martin Bagge.  (Closes: #487669, #491774)
  - Italian, thanks Luca Monducci.  (Closes: #493962)

[ Sam Hartman ]
* Translation Updates:
    - Dutch, Thanks Vincent Zweije, Closes: #495733

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * kdc/kerberos_v4.c
3
3
 *
4
 
 * Copyright 1985, 1986, 1987, 1988,1991 by the Massachusetts Institute
 
4
 * Copyright 1985, 1986, 1987, 1988,1991,2007 by the Massachusetts Institute
5
5
 * of Technology.
6
6
 * All Rights Reserved.
7
7
 *
26
26
 * 
27
27
 */
28
28
 
 
29
#include "autoconf.h"
29
30
#ifdef KRB5_KRB4_COMPAT
30
31
#define BACKWARD_COMPAT
31
32
 
52
53
#include <ctype.h>
53
54
#include <syslog.h>
54
55
#include <string.h>
 
56
#include <errno.h>
55
57
 
56
58
/* v4 include files:
57
59
 */
60
62
#include <klog.h>
61
63
#include <prot.h>
62
64
#include <krb_db.h>
63
 
#include <kdc.h>
64
65
 
65
66
#ifdef NEED_SWAB_PROTO
66
67
extern void swab(const void *, void *, size_t );
68
69
 
69
70
static int compat_decrypt_key (krb5_key_data *, C_Block,
70
71
                                         krb5_keyblock *, int);
71
 
static int kerb_get_principal (char *, char *, Principal *, int,
 
72
static int kerb_get_principal (char *, char *, Principal *,
72
73
                                         int *, krb5_keyblock *, krb5_kvno,
73
74
                                         int, krb5_deltat *);
74
75
static int check_princ (char *, char *, int, Principal *,
86
87
#define         MSB_FIRST               0       /* 68000, IBM RT/PC */
87
88
#define         LSB_FIRST               1       /* Vax, PC8086 */
88
89
 
89
 
int     f;
90
 
 
91
 
/* XXX several files in libkdb know about this */
92
 
char *progname;
93
 
 
94
90
#ifndef BACKWARD_COMPAT
95
91
static Key_schedule master_key_schedule;
96
92
static C_Block master_key;
143
139
#include "extern.h"             /* to pick up master_princ */
144
140
#include <errno.h>
145
141
 
146
 
static krb5_data *response;
147
 
 
148
 
void kerberos_v4 (struct sockaddr_in *, KTEXT);
149
 
void kerb_err_reply (struct sockaddr_in *, KTEXT, long, char *);
 
142
static krb5_data *kerberos_v4 (struct sockaddr_in *, KTEXT);
 
143
static krb5_data *kerb_err_reply (struct sockaddr_in *, KTEXT, long, char *);
150
144
static int set_tgtkey (char *, krb5_kvno, krb5_boolean);
151
145
 
152
146
/* Attributes converted from V5 to V4 - internal representation */
262
256
            (void) klog(L_KRB_PERR, "V4 request too long.");
263
257
            return KRB5KRB_ERR_FIELD_TOOLONG;
264
258
    }
 
259
    memset( &v4_pkt, 0, sizeof(v4_pkt));
265
260
    v4_pkt.length = pkt->length;
266
261
    v4_pkt.mbz = 0;
267
262
    memcpy( v4_pkt.dat, pkt->data, pkt->length);
268
263
 
269
 
    kerberos_v4( &client_sockaddr, &v4_pkt);
270
 
    *resp = response;
 
264
    *resp = kerberos_v4( &client_sockaddr, &v4_pkt);
271
265
    return(retval);
272
266
}
273
267
 
300
294
}
301
295
 
302
296
static
303
 
int krb4_sendto(int s, const char *msg, int len, int flags,
304
 
                const struct sockaddr *to, int to_len)
 
297
krb5_data *make_response(const char *msg, int len)
305
298
{
 
299
    krb5_data *response;
 
300
 
306
301
    if (  !(response = (krb5_data *) malloc( sizeof *response))) {
307
 
        return ENOMEM;
 
302
        return 0;
308
303
    }
309
304
    if ( !(response->data = (char *) malloc( len))) {
310
305
        krb5_free_data(kdc_context,  response);
311
 
        return ENOMEM;
 
306
        return 0;
312
307
    }
313
308
    response->length = len;
314
309
    memcpy( response->data, msg, len);
315
 
    return( 0);
 
310
    return response;
316
311
}
317
312
static void
318
313
hang(void)
400
395
static int
401
396
kerb_get_principal(char *name, char *inst, /* could have wild cards */
402
397
                   Principal *principal,
403
 
                   int maxn,    /* max # name structs to return */
404
398
                   int *more,   /* more tuples than room for */
405
399
                   krb5_keyblock *k5key, krb5_kvno kvno,
406
400
                   int issrv,   /* true if retrieving a service key */
423
417
    krb5_error_code retval;
424
418
 
425
419
    *more = 0;
426
 
    if ( maxn > 1) {
427
 
        lt = klog(L_DEATH_REQ, "KDC V4 is requesting too many principals");
428
 
        return( 0);
429
 
    }
430
420
    /* begin setting up the principal structure
431
421
     * with the first info we have:
432
422
     */
452
442
    krb5_free_principal(kdc_context, search);
453
443
 
454
444
    if (nprinc < 1) {
455
 
        *more = (int)more5 || (nprinc > maxn);
 
445
        *more = (int)more5 || (nprinc > 1);
456
446
        return(nprinc);
457
447
    } 
458
448
 
516
506
            return(0);
517
507
        }
518
508
        compat_decrypt_key(pkey, k, k5key, issrv);
519
 
    memset (k, 0, sizeof k);
520
 
        }
 
509
        memset (k, 0, sizeof k);
 
510
    }
521
511
 
522
512
 
523
513
    /*
575
565
     * this routine clears the keyblock's contents for us.
576
566
     */
577
567
    krb5_db_free_principal(kdc_context, &entries, nprinc);
578
 
    *more = (int) more5 || (nprinc > maxn);
 
568
    *more = (int) more5 || (nprinc > 1);
579
569
    return( nprinc);
580
570
}
581
571
 
591
581
        *cp = 0;
592
582
}
593
583
 
594
 
void
 
584
static krb5_data *
595
585
kerberos_v4(struct sockaddr_in *client, KTEXT pkt)
596
586
{
597
587
    static KTEXT_ST rpkt_st;
604
594
    KTEXT   auth = &auth_st;
605
595
    AUTH_DAT ad_st;
606
596
    AUTH_DAT *ad = &ad_st;
607
 
 
 
597
    krb5_data *response = 0;
608
598
 
609
599
    static struct in_addr client_host;
610
600
    static int msg_byte_order;
642
632
                  inet_ntoa(client_host));
643
633
        /* send an error reply */
644
634
        req_name_ptr = req_inst_ptr = req_realm_ptr = "";
645
 
        kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
646
 
        return;
 
635
        return kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
647
636
    }
648
637
 
649
638
    /* check packet version */
653
642
                  KRB_PROT_VERSION, req_version, 0);
654
643
        /* send an error reply */
655
644
        req_name_ptr = req_inst_ptr = req_realm_ptr = "";
656
 
        kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
657
 
        return;
 
645
        return kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
658
646
    }
659
647
    msg_byte_order = req_msg_type & 1;
660
648
 
712
700
 
713
701
            if ((i = check_princ(req_name_ptr, req_inst_ptr, 0,
714
702
                                 &a_name_data, &k5key, 0, &ck5life))) {
715
 
                kerb_err_reply(client, pkt, i, "check_princ failed");
 
703
                response = kerb_err_reply(client, pkt, i, "check_princ failed");
716
704
                a_name_data.key_low = a_name_data.key_high = 0;
717
705
                krb5_free_keyblock_contents(kdc_context, &k5key);
718
 
                return;
 
706
                return response;
719
707
            }
720
708
            /* don't use k5key for client */
721
709
            krb5_free_keyblock_contents(kdc_context, &k5key);
727
715
            /* this does all the checking */
728
716
            if ((i = check_princ(service, instance, lifetime,
729
717
                                 &s_name_data, &k5key, 1, &sk5life))) {
730
 
                kerb_err_reply(client, pkt, i, "check_princ failed");
 
718
                response = kerb_err_reply(client, pkt, i, "check_princ failed");
731
719
                a_name_data.key_high = a_name_data.key_low = 0;
732
720
                s_name_data.key_high = s_name_data.key_low = 0;
733
721
                krb5_free_keyblock_contents(kdc_context, &k5key);
734
 
                return;
 
722
                return response;
735
723
            }
736
724
            /* Bound requested lifetime with service and user */
737
725
            v4req_end = krb_life_to_time(kerb_time.tv_sec, req_life);
802
790
            rpkt = create_auth_reply(req_name_ptr, req_inst_ptr,
803
791
                req_realm_ptr, req_time_ws, 0, a_name_data.exp_date,
804
792
                a_name_data.key_version, ciph);
805
 
            krb4_sendto(f, (char *) rpkt->dat, rpkt->length, 0,
806
 
                   (struct sockaddr *) client, S_AD_SZ);
 
793
            response = make_response((char *) rpkt->dat, rpkt->length);
807
794
            memset(&a_name_data, 0, sizeof(a_name_data));
808
795
            memset(&s_name_data, 0, sizeof(s_name_data));
809
796
            break;
829
816
                lt = klog(L_KRB_PERR,
830
817
                          "APPL request with realm length too long from %s",
831
818
                          inet_ntoa(client_host));
832
 
                kerb_err_reply(client, pkt, RD_AP_INCON,
833
 
                               "realm length too long");
834
 
                return;
 
819
                return kerb_err_reply(client, pkt, RD_AP_INCON,
 
820
                                      "realm length too long");
835
821
            }
836
822
 
837
823
            auth->length += (int) *(pkt->dat + auth->length) +
840
826
                lt = klog(L_KRB_PERR,
841
827
                          "APPL request with funky tkt or req_id length from %s",
842
828
                          inet_ntoa(client_host));
843
 
                kerb_err_reply(client, pkt, RD_AP_INCON,
844
 
                               "funky tkt or req_id length");
845
 
                return;
 
829
                return kerb_err_reply(client, pkt, RD_AP_INCON,
 
830
                                      "funky tkt or req_id length");
846
831
            }
847
832
 
848
833
            memcpy(auth->dat, pkt->dat, auth->length);
853
838
            if ((!allow_v4_crossrealm)&&strcmp(tktrlm, local_realm) != 0) {
854
839
              lt = klog(L_ERR_UNK,
855
840
                        "Cross realm ticket from %s denied by policy,", tktrlm);
856
 
              kerb_err_reply(client, pkt,
857
 
                               KERB_ERR_PRINCIPAL_UNKNOWN, lt);
858
 
                return;
 
841
              return kerb_err_reply(client, pkt,
 
842
                                    KERB_ERR_PRINCIPAL_UNKNOWN, lt);
859
843
            }
860
844
            if (set_tgtkey(tktrlm, kvno, 0)) {
861
 
              lt = klog(L_ERR_UNK,
 
845
                lt = klog(L_ERR_UNK,
862
846
                          "FAILED set_tgtkey realm %s, kvno %d. Host: %s ",
863
847
                          tktrlm, kvno, inet_ntoa(client_host));
864
848
                /* no better error code */
865
 
                kerb_err_reply(client, pkt,
866
 
                               KERB_ERR_PRINCIPAL_UNKNOWN, lt);
867
 
                return;
 
849
                return kerb_err_reply(client, pkt,
 
850
                                      KERB_ERR_PRINCIPAL_UNKNOWN, lt);
868
851
            }
869
852
            kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
870
853
                ad, 0);
874
857
                              "FAILED 3des set_tgtkey realm %s, kvno %d. Host: %s ",
875
858
                              tktrlm, kvno, inet_ntoa(client_host));
876
859
                    /* no better error code */
877
 
                    kerb_err_reply(client, pkt,
878
 
                                   KERB_ERR_PRINCIPAL_UNKNOWN, lt);
879
 
                    return;
 
860
                    return kerb_err_reply(client, pkt,
 
861
                                          KERB_ERR_PRINCIPAL_UNKNOWN, lt);
880
862
                }
881
863
                kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
882
864
                                   ad, 0);
886
868
                klog(L_ERR_UNK, "FAILED krb_rd_req from %s: %s",
887
869
                     inet_ntoa(client_host), krb_get_err_text(kerno));
888
870
                req_name_ptr = req_inst_ptr = req_realm_ptr = "";
889
 
                kerb_err_reply(client, pkt, kerno, "krb_rd_req failed");
890
 
                return;
 
871
                return kerb_err_reply(client, pkt, kerno, "krb_rd_req failed");
891
872
            }
892
873
            ptr = (char *) pkt->dat + auth->length;
893
874
 
909
890
            req_realm_ptr = ad->prealm;
910
891
 
911
892
            if (strcmp(ad->prealm, tktrlm)) {
912
 
                kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
913
 
                     "Can't hop realms");
914
 
                return;
 
893
                return kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
 
894
                                      "Can't hop realms");
915
895
            }
916
896
            if (!strcmp(service, "changepw")) {
917
 
                kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
918
 
                     "Can't authorize password changed based on TGT");
919
 
                return;
 
897
                return kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
 
898
                                      "Can't authorize password changed based on TGT");
920
899
            }
921
900
            kerno = check_princ(service, instance, req_life,
922
901
                                &s_name_data, &k5key, 1, &sk5life);
923
902
            if (kerno) {
924
 
                kerb_err_reply(client, pkt, kerno, "check_princ failed");
 
903
                response = kerb_err_reply(client, pkt, kerno,
 
904
                                          "check_princ failed");
925
905
                s_name_data.key_high = s_name_data.key_low = 0;
926
906
                krb5_free_keyblock_contents(kdc_context, &k5key);
927
 
                return;
 
907
                return response;
928
908
            }
929
909
            /* Bound requested lifetime with service and user */
930
910
            v4endtime = krb_life_to_time((KRB4_32)ad->time_sec, ad->life);
980
960
            rpkt = create_auth_reply(ad->pname, ad->pinst,
981
961
                                     ad->prealm, time_ws,
982
962
                                     0, 0, 0, ciph);
983
 
            krb4_sendto(f, (char *) rpkt->dat, rpkt->length, 0,
984
 
                   (struct sockaddr *) client, S_AD_SZ);
 
963
            response = make_response((char *) rpkt->dat, rpkt->length);
985
964
            memset(&s_name_data, 0, sizeof(s_name_data));
986
965
            break;
987
966
        }
1006
985
            break;
1007
986
        }
1008
987
    }
 
988
    return response;
1009
989
}
1010
990
 
1011
991
 
1015
995
 * client. 
1016
996
 */
1017
997
 
1018
 
void
 
998
static krb5_data *
1019
999
kerb_err_reply(struct sockaddr_in *client, KTEXT pkt, long int err, char *string)
1020
1000
{
1021
1001
    static KTEXT_ST e_pkt_st;
1026
1006
    strncat(e_msg, string, sizeof(e_msg) - 1 - 19);
1027
1007
    cr_err_reply(e_pkt, req_name_ptr, req_inst_ptr, req_realm_ptr,
1028
1008
                 req_time_ws, err, e_msg);
1029
 
    krb4_sendto(f, (char *) e_pkt->dat, e_pkt->length, 0,
1030
 
           (struct sockaddr *) client, S_AD_SZ);
1031
 
 
 
1009
    return make_response((char *) e_pkt->dat, e_pkt->length);
1032
1010
}
1033
1011
 
1034
1012
static int
1039
1017
    static int more;
1040
1018
 /* long trans; */
1041
1019
 
1042
 
    n = kerb_get_principal(p_name, instance, p, 1, &more, k5key, 0,
 
1020
    n = kerb_get_principal(p_name, instance, p, &more, k5key, 0,
1043
1021
                           issrv, k5life);
1044
1022
    klog(L_ALL_REQ,
1045
1023
         "Principal: \"%s\", Instance: \"%s\" Lifetime = %d n = %d",
1160
1138
 
1161
1139
/*  log("Getting key for %s", r); */
1162
1140
 
1163
 
    n = kerb_get_principal("krbtgt", r, p, 1, &more, &k5key, kvno, 1, NULL);
 
1141
    n = kerb_get_principal("krbtgt", r, p, &more, &k5key, kvno, 1, NULL);
1164
1142
    if (n == 0)
1165
1143
        return (KFAILURE);
1166
1144