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

« back to all changes in this revision

Viewing changes to src/lib/krb4/tf_util.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-10-30 10:28:53 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20061030102853-x7v876vw4af46v0m
Tags: 1.4.4-3ubuntu1
* Merge with Debian; only Ubuntu change:
  - src/include/k5-thread.h: Define__USE_GNU when #include'ing pthread.h to
    fix FTBFS (from 1.4.3-9ubuntu1).

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include "k5-int.h"
29
29
#include "krb4int.h"
30
30
 
 
31
#include "../crypto/aes/aesopt.h"
 
32
 
31
33
#include <stdio.h>
32
34
#include <string.h>
33
35
#include <errno.h>
43
45
#include <sys/shm.h>
44
46
#endif /* TKT_SHMEM */
45
47
 
 
48
 
 
49
 
46
50
#define TOO_BIG -1
47
51
#define TF_LCK_RETRY ((unsigned)2)      /* seconds to sleep before
48
52
                                         * retry if ticket file is
93
97
#endif
94
98
#endif
95
99
 
 
100
 
 
101
#if (PLATFORM_BYTE_ORDER == AES_LITTLE_ENDIAN)
 
102
/* This was taken from jhutz's patch for heimdal krb4. It only
 
103
 * applies to little endian systems. Big endian systems have a
 
104
 * less elegant solution documented below.
 
105
 *
 
106
 * This record is written after every real ticket, to ensure that
 
107
 * both 32- and 64-bit readers will perceive the next real ticket
 
108
 * as starting in the same place.  This record looks like a ticket
 
109
 * with the following properties:
 
110
 *   Field         32-bit             64-bit
 
111
 *   ============  =================  =================
 
112
 *   sname         "."                "."
 
113
 *   sinst         ""                 ""
 
114
 *   srealm        ".."               ".."
 
115
 *   session key   002E2E00 xxxxxxxx  xxxxxxxx 00000000
 
116
 *   lifetime      0                  0
 
117
 *   kvno          0                  12
 
118
 *   ticket        12 nulls           4 nulls
 
119
 *   issue         0                  0
 
120
 *
 
121
 * Our code always reads and writes the 32-bit format, but knows
 
122
 * to skip 00000000 at the front of a record, and to completely
 
123
 * ignore tickets for the special alignment principal.
 
124
 */
 
125
static unsigned char align_rec[] = {
 
126
    0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00, 0x2e,
 
127
    0x2e, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
 
128
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
 
129
    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
 
130
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
131
    0x00, 0x00
 
132
};
 
133
 
 
134
#else /* Big Endian */
 
135
 
 
136
/* These alignment records are for big endian systems. We need more
 
137
 * of them because the portion of the 64-bit issue_date that overlaps
 
138
 * with the start of a ticket on 32-bit systems contains an unpredictable
 
139
 * number of NULL bytes. Preceeding these records is a second copy of the
 
140
 * 32-bit issue_date. The srealm for the alignment records is always one of
 
141
 * ".." or "?.."
 
142
 */
 
143
 
 
144
/* No NULL bytes
 
145
 * This is actually two alignment records since both 32- and 64-bit
 
146
 * readers will agree on everything in the first record up through the
 
147
 * issue_date size, except where sname starts.
 
148
 *   Field (1)     32-bit             64-bit
 
149
 *   ============  =================  =================
 
150
 *   sname         "????."            "."
 
151
 *   sinst         ""                 ""
 
152
 *   srealm        ".."               ".."
 
153
 *   session key   00000000 xxxxxxxx  00000000 xxxxxxxx
 
154
 *   lifetime      0                  0
 
155
 *   kvno          0                  0
 
156
 *   ticket        4 nulls           4 nulls
 
157
 *   issue         0                  0
 
158
 *
 
159
 *   Field (2)     32-bit             64-bit
 
160
 *   ============  =================  =================
 
161
 *   sname         "."                "."
 
162
 *   sinst         ""                 ""
 
163
 *   srealm        ".."               ".."
 
164
 *   session key   002E2E00 xxxxxxxx  xxxxxxxx 00000000
 
165
 *   lifetime      0                  0
 
166
 *   kvno          0                  12
 
167
 *   ticket        12 nulls           4 nulls
 
168
 *   issue         0                  0
 
169
 *
 
170
 */
 
171
static unsigned char align_rec_0[] = {
 
172
    0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0x00, 0x00,
 
173
    0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
 
174
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
175
    0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
176
    0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00,
 
177
    0x00, 0x2e, 0x2e, 0x00, 0xff, 0xff, 0xff, 0xff,
 
178
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
179
    0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04,
 
180
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
181
    0x00, 0x00, 0x00, 0x00
 
182
};
 
183
 
 
184
/* One NULL byte
 
185
 *   Field         32-bit             64-bit
 
186
 *   ============  =================  =================
 
187
 *   sname         "x"  |"xx"|"xxx"   "."
 
188
 *   sinst         "xx."|"x."|"."     ".."
 
189
 *   srealm        ".."               "..."
 
190
 *   session key   2E2E2E00 xxxxxxxx  xxxxxxxx 00000000
 
191
 *   lifetime      0                  0
 
192
 *   kvno          0                  12
 
193
 *   ticket        12 nulls           4 nulls
 
194
 *   issue         0                  0
 
195
 */
 
196
static unsigned char align_rec_1[] = {
 
197
    0x2e, 0x00, 0x2e, 0x2e, 0x00, 0x2e, 0x2e, 0x2e,
 
198
    0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
 
199
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
200
    0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
 
201
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
202
    0x00
 
203
};
 
204
 
 
205
/* Two NULL bytes
 
206
 *   Field         32-bit             64-bit
 
207
 *   ============  =================  =================
 
208
 *   sname         "x"  |"x" |"xx"    ".."
 
209
 *   sinst         ""   |"x" |""      ""
 
210
 *   srealm        "x.."|".."|".."    ".."
 
211
 *   session key   002E2E00 xxxxxxxx  xxxxxxxx 00000000
 
212
 *   lifetime      0                  0
 
213
 *   kvno          0                  12
 
214
 *   ticket        12 nulls           4 nulls
 
215
 *   issue         0                  0
 
216
 */
 
217
 static unsigned char align_rec_2[] = {
 
218
    0x2e, 0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0xff,
 
219
    0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
 
220
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
 
221
    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
 
222
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 
223
};
 
224
 
 
225
/* Three NULL bytes
 
226
 * Things break here for 32-bit krb4 libraries that don't
 
227
 * understand this alignment record. We can't really do
 
228
 * anything about the fact that the three strings ended
 
229
 * in the duplicate timestamp. The good news is that this
 
230
 * only happens once every 0x1000000 seconds, once roughly
 
231
 * every six and a half months. We'll live.
 
232
 *
 
233
 * Discussion on the krbdev list has suggested the
 
234
 * issue_date be incremented by one in this case to avoid
 
235
 * the problem. I'm leaving this here just in case.
 
236
 *
 
237
 *   Field         32-bit             64-bit
 
238
 *   ============  =================  =================
 
239
 *   sname         ""                 "."
 
240
 *   sinst         ""                 ""
 
241
 *   srealm        ""                 ".."
 
242
 *   session key   2E00002E 2E00FFFF  xxxx0000 0000xxxx
 
243
 *   lifetime      0                  0
 
244
 *   kvno          4294901760         917504
 
245
 *   ticket        14 nulls           4 nulls
 
246
 *   issue         0                  0
 
247
 */
 
248
/*
 
249
static unsigned char align_rec_3[] = {
 
250
    0x2e, 0x00, 0x00, 0x2e, 0x2e, 0x00, 0xff, 0xff,
 
251
    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
 
252
    0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
 
253
    0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
254
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 
255
};
 
256
*/
 
257
#endif /* (PLATFORM_BYTE_ORDER == AES_LITTLE_ENDIAN) */
 
258
 
96
259
/*
97
260
 * fd must be initialized to something that won't ever occur as a real
98
261
 * file descriptor. Since open(2) returns only non-negative numbers as
136
299
 *              int             lifetime
137
300
 *              int             kvno
138
301
 *              KTEXT_ST        ticket_st
139
 
 *              long            issue_date
 
302
 *              KRB4_32         issue_date
140
303
 *
141
304
 * Strings are stored NUL-terminated, and read back until a NUL is
142
305
 * found or the indicated number of bytes have been read.  (So if you
519
682
 * EOF          - end of file encountered
520
683
 */
521
684
 
522
 
int KRB5_CALLCONV tf_get_cred(c)
 
685
int KRB5_CALLCONV real_tf_get_cred(c)
523
686
    CREDENTIALS *c;
524
687
{
525
688
    KTEXT   ticket = &c->ticket_st;     /* pointer to ticket */
526
689
    int     k_errno;
527
 
    long issue_date;
 
690
    unsigned char nullbuf[3];  /* used for 64-bit issue_date tf compatibility */
528
691
 
529
692
    if (fd < 0) {
530
693
        if (krb_debug)
531
694
            fprintf(stderr, "tf_get_cred called before tf_init.\n");
532
695
        return TKT_FIL_INI;
533
696
    }
534
 
    if ((k_errno = tf_gets(c->service, SNAME_SZ)) < 2)
 
697
    if ((k_errno = tf_gets(c->service, SNAME_SZ)) < 2) {
 
698
 
 
699
#if (PLATFORM_BYTE_ORDER == AES_BIG_ENDIAN)
 
700
        /* If we're big endian then we can have a null service name as part of
 
701
         * an alignment record. */
 
702
        if (k_errno < 2)
 
703
            switch (k_errno) {
 
704
            case TOO_BIG:
 
705
                tf_close();
 
706
                return TKT_FIL_FMT;
 
707
            case 0:
 
708
                return EOF;
 
709
            }
 
710
#else /* Little Endian */
 
711
        /* If we read an empty service name, it's possible that's because
 
712
         * the file was written by someone who thinks issue_date should be
 
713
         * 64 bits.  If that is the case, there will be three more zeros,
 
714
         * followed by the real record.*/
 
715
 
 
716
        if (k_errno == 1 && 
 
717
            tf_read(nullbuf, 3) == 3 &&
 
718
            !nullbuf[0] && !nullbuf[1] && !nullbuf[2])
 
719
            k_errno = tf_gets(c->service, SNAME_SZ);
 
720
 
 
721
        if (k_errno < 2)
535
722
        switch (k_errno) {
536
723
        case TOO_BIG:
537
724
        case 1:         /* can't be just a null */
540
727
        case 0:
541
728
            return EOF;
542
729
        }
 
730
#endif /*(PLATFORM_BYTE_ORDER == AES_BIG_ENDIAN)*/
 
731
 
 
732
    }
543
733
    if ((k_errno = tf_gets(c->instance, INST_SZ)) < 1)
544
734
        switch (k_errno) {
545
735
        case TOO_BIG:
547
737
        case 0:
548
738
            return EOF;
549
739
        }
550
 
    if ((k_errno = tf_gets(c->realm, REALM_SZ)) < 2)
 
740
    if ((k_errno = tf_gets(c->realm, REALM_SZ)) < 2) {
551
741
        switch (k_errno) {
552
742
        case TOO_BIG:
553
743
        case 1:         /* can't be just a null */
556
746
        case 0:
557
747
            return EOF;
558
748
        }
 
749
    }
 
750
    
559
751
    if (
560
752
        tf_read((char *) (c->session), KEY_SZ) < 1 ||
561
753
        tf_read((char *) &(c->lifetime), sizeof(c->lifetime)) < 1 ||
565
757
    /* don't try to read a silly amount into ticket->dat */
566
758
        ticket->length > MAX_KTXT_LEN ||
567
759
        tf_read((char *) (ticket->dat), ticket->length) < 1 ||
568
 
        tf_read((char *) &(issue_date), sizeof(issue_date)) < 1
 
760
        tf_read((char *) &(c->issue_date), sizeof(c->issue_date)) < 1
569
761
        ) {
570
762
        tf_close();
571
763
        return TKT_FIL_FMT;
572
764
    }
573
 
    c->issue_date = issue_date;
 
765
 
 
766
#if (PLATFORM_BYTE_ORDER == AES_BIG_ENDIAN)
 
767
    /* If the issue_date is 0 and we're not dealing with an alignment
 
768
       record, then it's likely we've run into an issue_date written by
 
769
       a 64-bit library that is using long instead of KRB4_32. Let's get
 
770
       the next four bytes instead.
 
771
     */
 
772
    if (0 == c->issue_date) {
 
773
        int len = strlen(c->realm);
 
774
        if (!(2 == len && 0 == strcmp(c->realm, "..")) &&
 
775
            !(3 == len && 0 == strcmp(c->realm + 1, ".."))) {
 
776
            if (tf_read((char *) &(c->issue_date), sizeof(c->issue_date)) < 1) {
 
777
                tf_close();
 
778
                return TKT_FIL_FMT;
 
779
            }
 
780
        }
 
781
    }
 
782
 
 
783
#endif
 
784
    
 
785
    return KSUCCESS;
 
786
}
 
787
 
 
788
int KRB5_CALLCONV tf_get_cred(c)
 
789
    CREDENTIALS *c;
 
790
{
 
791
    int     k_errno;
 
792
    int     fake;
 
793
    
 
794
    do {
 
795
        fake = 0;
 
796
        k_errno = real_tf_get_cred(c);
 
797
        if (k_errno)
 
798
            return k_errno;
 
799
        
 
800
#if (PLATFORM_BYTE_ORDER == AES_BIG_ENDIAN)
 
801
        /* Here we're checking to see if the realm is one of the 
 
802
         * alignment record realms, ".." or "?..", so we can skip it.
 
803
         * If it's not, then we need to verify that the service name
 
804
         * was not null as this should be a valid ticket.
 
805
         */
 
806
        {
 
807
            int len = strlen(c->realm);
 
808
            if (2 == len && 0 == strcmp(c->realm, ".."))
 
809
                fake = 1;
 
810
            if (3 == len && 0 == strcmp(c->realm + 1, ".."))
 
811
                fake = 1;
 
812
            if (!fake && 0 == strlen(c->service)) {
 
813
                tf_close();
 
814
                return TKT_FIL_FMT;
 
815
            }
 
816
        }
 
817
#else /* Little Endian */
 
818
        /* Here we're checking to see if the service principal is the
 
819
         * special alignment record principal ".@..", so we can skip it.
 
820
         */
 
821
        if (strcmp(c->service, ".") == 0 &&
 
822
            strcmp(c->instance, "") == 0 &&
 
823
            strcmp(c->realm, "..") == 0)
 
824
            fake = 1;
 
825
#endif /* (PLATFORM_BYTE_ORDER == AES_BIG_ENDIAN) */
 
826
    } while (fake);
 
827
    
574
828
#ifdef TKT_SHMEM
575
829
    memcpy(c->session, tmp_shm_addr, KEY_SZ);
576
830
    tmp_shm_addr += KEY_SZ;
711
965
    int     lifetime;           /* Lifetime */
712
966
    int     kvno;               /* Key version number */
713
967
    KTEXT   ticket;             /* The ticket itself */
714
 
    long    issue_date;         /* The issue time */
 
968
    KRB4_32 issue_date;         /* The issue time */
715
969
{
716
970
 
717
971
    off_t   lseek();
777
1031
    if (write(fd, (char *) (ticket->dat), count) != count)
778
1032
        goto bad;
779
1033
    /* Issue date */
780
 
    if (write(fd, (char *) &issue_date, sizeof(long))
781
 
        != sizeof(long))
782
 
        goto bad;
 
1034
    if (write(fd, (char *) &issue_date, sizeof(KRB4_32))
 
1035
        != sizeof(KRB4_32))
 
1036
        goto bad;
 
1037
    /* Alignment Record */
 
1038
#if (PLATFORM_BYTE_ORDER == AES_BIG_ENDIAN)
 
1039
    {
 
1040
        int null_bytes = 0;
 
1041
        if (0 == (issue_date & 0xff000000))
 
1042
            ++null_bytes;
 
1043
        if (0 == (issue_date & 0x00ff0000))
 
1044
            ++null_bytes;
 
1045
        if (0 == (issue_date & 0x0000ff00))
 
1046
            ++null_bytes;
 
1047
        if (0 == (issue_date & 0x000000ff))
 
1048
            ++null_bytes;
 
1049
        
 
1050
        switch(null_bytes) {
 
1051
        case 0:
 
1052
            /* Issue date */
 
1053
            if (write(fd, (char *) &issue_date, sizeof(KRB4_32))
 
1054
                != sizeof(KRB4_32))
 
1055
        goto bad;
 
1056
            if (write(fd, align_rec_0, sizeof(align_rec_0))
 
1057
                != sizeof(align_rec_0))
 
1058
                goto bad;
 
1059
            break;
 
1060
            
 
1061
        case 1:
 
1062
            if (write(fd, (char *) &issue_date, sizeof(KRB4_32))
 
1063
                != sizeof(KRB4_32))
 
1064
                goto bad;
 
1065
            if (write(fd, align_rec_1, sizeof(align_rec_1))
 
1066
                != sizeof(align_rec_1))
 
1067
                goto bad;
 
1068
            break;
 
1069
            
 
1070
        case 3:
 
1071
            /* Three NULLS are troublesome but rare. We'll just pretend 
 
1072
             * they don't exist by decrementing the issue_date.
 
1073
             */
 
1074
            --issue_date;
 
1075
        case 2:
 
1076
            if (write(fd, (char *) &issue_date, sizeof(KRB4_32))
 
1077
                != sizeof(KRB4_32))
 
1078
                goto bad;
 
1079
            if (write(fd, align_rec_2, sizeof(align_rec_2))
 
1080
                != sizeof(align_rec_2))
 
1081
                goto bad;
 
1082
            break;
 
1083
            
 
1084
        default:
 
1085
            goto bad;
 
1086
        }
 
1087
        
 
1088
    }    
 
1089
#else
 
1090
    if (write(fd, align_rec, sizeof(align_rec)) != sizeof(align_rec))
 
1091
        goto bad;
 
1092
#endif 
783
1093
 
784
1094
    /* Actually, we should check each write for success */
785
1095
    return (KSUCCESS);