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

« back to all changes in this revision

Viewing changes to src/appl/bsd/kcmd.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2009-05-07 16:16:34 UTC
  • mfrom: (13.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090507161634-xqyk0s9na0le4flj
Tags: 1.7dfsg~beta1-4
When  decrypting the TGS response fails with the subkey, try with the
session key to work around Heimdal bug, Closes: #527353 

Show diffs side-by-side

added added

removed removed

Lines of Context:
89
89
#include <netdb.h>
90
90
 
91
91
#include <errno.h>
92
 
#include <krb5.h>
93
 
#ifdef KRB5_KRB4_COMPAT
94
 
#include <kerberosIV/krb.h>
95
 
#endif
 
92
#include "k5-int.h"
96
93
 
97
94
#include "defines.h"
98
95
 
99
96
extern krb5_context bsd_context;
100
 
#ifdef KRB5_KRB4_COMPAT
101
 
extern Key_schedule v4_schedule;
102
 
#endif
103
97
 
104
98
 
105
99
#define START_PORT      5120     /* arbitrary */
140
134
static int twrite(int, char *, size_t, int);
141
135
static int v5_des_read(int, char *, size_t, int), 
142
136
    v5_des_write(int, char *, size_t, int);
143
 
#ifdef KRB5_KRB4_COMPAT
144
 
static int v4_des_read(int, char *, size_t, int), 
145
 
    v4_des_write(int, char *, size_t, int);
146
 
static C_Block v4_session;
147
 
static int right_justify;
148
 
#endif
149
137
static int do_lencheck;
150
138
 
151
 
#ifdef KRB5_KRB4_COMPAT
152
 
extern int
153
 
krb_sendauth(long options, int fd, KTEXT ticket,
154
 
             char *service, char *inst, char *realm,
155
 
             unsigned KRB4_32 checksum,
156
 
             MSG_DAT *msg_data,
157
 
             CREDENTIALS *cred,
158
 
             Key_schedule schedule,
159
 
             struct sockaddr_in *laddr,
160
 
             struct sockaddr_in *faddr,
161
 
             char *version);
162
 
#endif
163
 
 
164
139
#ifdef POSIX_SIGNALS
165
140
typedef sigset_t masktype;
166
141
#else
205
180
        fprintf(stderr, "can't connect to %s port 0\n", hname);
206
181
        return -1;
207
182
    }
208
 
    sprintf(rport_buf, "%d", ntohs(rport));
 
183
    snprintf(rport_buf, sizeof(rport_buf), "%d", ntohs(rport));
209
184
    memset(&aihints, 0, sizeof(aihints));
210
185
    aihints.ai_socktype = SOCK_STREAM;
211
186
    aihints.ai_flags = AI_CANONNAME;
334
309
        FD_SET(s, &xfds);
335
310
        listen(s2, 1);
336
311
        FD_SET(s2, &rfds);
337
 
        (void) sprintf(num, "%d", *lportp);
 
312
        (void) snprintf(num, sizeof(num), "%d", *lportp);
338
313
        slen = strlen(num)+1;
339
314
        if (write(s, num, slen) != slen) {
340
315
            perror("write: setting up stderr");
424
399
    enum kcmd_proto protonum = *protonump;
425
400
    int addrfamily = /* AF_INET */0;
426
401
 
427
 
    if ((cksumbuf = malloc(strlen(cmd)+strlen(remuser)+64)) == 0 ) {
 
402
    if (asprintf(&cksumbuf, "%u:%s%s", ntohs(rport), cmd, remuser) < 0) {
428
403
        fprintf(stderr, "Unable to allocate memory for checksum buffer.\n");
429
404
        return(-1);
430
405
    }
431
 
    sprintf(cksumbuf, "%u:", ntohs(rport));
432
 
    strcat(cksumbuf, cmd);
433
 
    strcat(cksumbuf, remuser);
434
406
    cksumdat.data = cksumbuf;
435
407
    cksumdat.length = strlen(cksumbuf);
436
408
        
501
473
    if (krb5_auth_con_init(bsd_context, &auth_context)) 
502
474
        goto bad2;
503
475
 
 
476
    if (krb5_auth_con_set_req_cksumtype(bsd_context, auth_context, CKSUMTYPE_RSA_MD5) !=0 )
 
477
        goto bad2;
504
478
    if (krb5_auth_con_setflags(bsd_context, auth_context, 
505
479
                               KRB5_AUTH_CONTEXT_RET_TIME))
506
480
        goto bad2;
634
608
}
635
609
 
636
610
 
637
 
 
638
 
#ifdef KRB5_KRB4_COMPAT
639
 
int
640
 
k4cmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm,
641
 
      cred, schedule, msg_data, laddr, faddr, authopts, anyport)
642
 
     int *sock;
643
 
     char **ahost;
644
 
     unsigned int rport;
645
 
     char *locuser, *remuser, *cmd;
646
 
     int *fd2p;
647
 
     KTEXT ticket;
648
 
     char *service;
649
 
     char *realm;
650
 
     CREDENTIALS *cred;
651
 
     Key_schedule schedule;
652
 
     MSG_DAT *msg_data;
653
 
     struct sockaddr_in *laddr, *faddr;
654
 
     long authopts;
655
 
     int anyport;
656
 
{
657
 
    int s;
658
 
    masktype oldmask;
659
 
    struct sockaddr_in sockin, from;
660
 
    char c;
661
 
    int lport = START_PORT;
662
 
    int rc;
663
 
    char *host_save;
664
 
    int status;
665
 
    int addrfamily = AF_INET;
666
 
 
667
 
    block_urgent(&oldmask);
668
 
    if (kcmd_connect (&s, &addrfamily, &sockin, *ahost, &host_save, rport, &lport, laddr) == -1) {
669
 
        restore_sigs(&oldmask);
670
 
        return -1;
671
 
    }
672
 
    *ahost = host_save;
673
 
    /* If realm is null, look up from table */
674
 
    if ((realm == NULL) || (realm[0] == '\0')) {
675
 
        realm = krb_realmofhost(host_save);
676
 
    }
677
 
    lport--;
678
 
    status = setup_secondary_channel(s, fd2p, &lport, &addrfamily, &from,
679
 
                                     anyport);
680
 
    if (status)
681
 
        goto bad;
682
 
 
683
 
    /* set up the needed stuff for mutual auth */
684
 
    *faddr = sockin;
685
 
 
686
 
    status = krb_sendauth(authopts, s, ticket, service, *ahost,
687
 
                          realm, (unsigned long) getpid(), msg_data,
688
 
                          cred, schedule, laddr, faddr, "KCMDV0.1");
689
 
    if (status != KSUCCESS) {
690
 
        fprintf(stderr, "krb_sendauth failed: %s\n", krb_get_err_text(status));
691
 
        status = -1;
692
 
        goto bad2;
693
 
    }
694
 
    (void) write(s, remuser, strlen(remuser)+1);
695
 
    (void) write(s, cmd, strlen(cmd)+1);
696
 
 
697
 
reread:
698
 
    if ((rc=read(s, &c, 1)) != 1) {
699
 
        if (rc==-1) {
700
 
            perror(*ahost);
701
 
        } else {
702
 
            fprintf(stderr,"rcmd: bad connection with remote host\n");
703
 
        }
704
 
        status = -1;
705
 
        goto bad2;
706
 
    }
707
 
    if (c != 0) {
708
 
        /* If rlogind was compiled on SunOS4, and it somehow
709
 
           got the shared library version numbers wrong, it
710
 
           may give an ld.so warning about an old version of a
711
 
           shared library.  Just ignore any such warning.
712
 
           Note that the warning is a characteristic of the
713
 
           server; we may not ourselves be running under
714
 
           SunOS4.  */
715
 
        if (c == 'l') {
716
 
            char *check = "d.so: warning:";
717
 
            char *p;
718
 
            char cc;
719
 
 
720
 
            p = check;
721
 
            while (read(s, &c, 1) == 1) {
722
 
                if (*p == '\0') {
723
 
                    if (c == '\n')
724
 
                        break;
725
 
                } else {
726
 
                    if (c != *p)
727
 
                        break;
728
 
                    ++p;
729
 
                }
730
 
            }
731
 
 
732
 
            if (*p == '\0')
733
 
                goto reread;
734
 
 
735
 
            cc = 'l';
736
 
            (void) write(2, &cc, 1);
737
 
            if (p != check)
738
 
                (void) write(2, check, (unsigned) (p - check));
739
 
        }
740
 
 
741
 
        (void) write(2, &c, 1);
742
 
        while (read(s, &c, 1) == 1) {
743
 
            (void) write(2, &c, 1);
744
 
            if (c == '\n')
745
 
                break;
746
 
        }
747
 
        status = -1;
748
 
        goto bad2;
749
 
    }
750
 
    restore_sigs(&oldmask);
751
 
    *sock = s;
752
 
    return (KSUCCESS);
753
 
 bad2:
754
 
    if (lport)
755
 
        (void) close(*fd2p);
756
 
 bad:
757
 
    (void) close(s);
758
 
    restore_sigs(&oldmask);
759
 
    return (status);
760
 
}
761
 
#endif /* KRB5_KRB4_COMPAT */
762
 
 
763
 
 
764
611
static int
765
612
setup_socket (struct sockaddr *sa, GETSOCKNAME_ARG3_TYPE len)
766
613
{
940
787
    abort();
941
788
    }
942
789
 
943
 
#ifdef KRB5_KRB4_COMPAT
944
 
void rcmd_stream_init_krb4(session, encrypt_flag, lencheck, justify)
945
 
     C_Block session;
946
 
     int encrypt_flag;
947
 
     int lencheck;
948
 
     int justify;
949
 
{
950
 
    if (!encrypt_flag) {
951
 
        rcmd_stream_init_normal();
952
 
        return;
953
 
    }
954
 
    do_lencheck = lencheck;
955
 
    right_justify = justify;
956
 
    input = v4_des_read;
957
 
    output = v4_des_write;
958
 
    memcpy(v4_session, session, sizeof(v4_session));
959
 
}
960
 
#endif
961
 
 
962
790
int rcmd_stream_read(fd, buf, len, sec)
963
791
     int fd;
964
792
     register char *buf;
1014
842
        nstored = 0;
1015
843
    }
1016
844
 
1017
 
    /* See the comment in v4_des_read. */
1018
845
    while (1) {
1019
846
        cc = krb5_net_read(bsd_context, fd, &c, 1);
1020
847
        /* we should check for non-blocking here, but we'd have
1153
980
}
1154
981
 
1155
982
 
1156
 
 
1157
 
#ifdef KRB5_KRB4_COMPAT
1158
 
 
1159
 
static int
1160
 
v4_des_read(fd, buf, len, secondary)
1161
 
int fd;
1162
 
char *buf;
1163
 
size_t len;
1164
 
int secondary;
1165
 
{
1166
 
        int nreturned = 0;
1167
 
        krb5_ui_4 net_len, rd_len;
1168
 
        int cc;
1169
 
        unsigned char c;
1170
 
 
1171
 
        if (nstored >= len) {
1172
 
                memcpy(buf, store_ptr, len);
1173
 
                store_ptr += len;
1174
 
                nstored -= len;
1175
 
                return(len);
1176
 
        } else if (nstored) {
1177
 
                memcpy(buf, store_ptr, nstored);
1178
 
                nreturned += nstored;
1179
 
                buf += nstored;
1180
 
                len -= nstored;
1181
 
                nstored = 0;
1182
 
        }
1183
 
 
1184
 
        /* We're fetching the length which is MSB first, and the MSB
1185
 
           has to be zero unless the client is sending more than 2^24
1186
 
           (16M) bytes in a single write (which is why this code is used
1187
 
           in rlogin but not rcp or rsh.) The only reasons we'd get
1188
 
           something other than zero are:
1189
 
                -- corruption of the tcp stream (which will show up when
1190
 
                   everything else is out of sync too)
1191
 
                -- un-caught Berkeley-style "pseudo out-of-band data" which
1192
 
                   happens any time the user hits ^C twice.
1193
 
           The latter is *very* common, as shown by an 'rlogin -x -d' 
1194
 
           using the CNS V4 rlogin.         Mark EIchin 1/95
1195
 
           */
1196
 
        while (1) {
1197
 
            cc = krb_net_read(fd, &c, 1);
1198
 
            if (cc <= 0) return cc; /* read error */
1199
 
            if (cc == 1) {
1200
 
                if (c == 0 || !do_lencheck) break;
1201
 
            }
1202
 
        }
1203
 
 
1204
 
        net_len = c;
1205
 
        if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
1206
 
        net_len = (net_len << 8) | c;
1207
 
        if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
1208
 
        net_len = (net_len << 8) | c;
1209
 
        if ((cc = krb_net_read(fd, &c, 1)) != 1) return 0;
1210
 
        net_len = (net_len << 8) | c;
1211
 
 
1212
 
        /* Note: net_len is unsigned */
1213
 
        if (net_len > sizeof(des_inbuf)) {
1214
 
                errno = EIO;
1215
 
                return(-1);
1216
 
        }
1217
 
        /* the writer tells us how much real data we are getting, but
1218
 
           we need to read the pad bytes (8-byte boundary) */
1219
 
        rd_len = roundup(net_len, 8);
1220
 
        if ((cc = krb_net_read(fd, des_inbuf, rd_len)) != rd_len) {
1221
 
                errno = EIO;
1222
 
                return(-1);
1223
 
        }
1224
 
        (void) pcbc_encrypt((des_cblock *) des_inbuf,
1225
 
                            (des_cblock *) storage,
1226
 
                            (int) ((net_len < 8) ? 8 : net_len),
1227
 
                            v4_schedule,
1228
 
                            &v4_session,
1229
 
                            DECRYPT);
1230
 
        /* 
1231
 
         * when the cleartext block is < 8 bytes, it is "right-justified"
1232
 
         * in the block, so we need to adjust the pointer to the data
1233
 
         */
1234
 
        if (net_len < 8 && right_justify)
1235
 
                store_ptr = storage + 8 - net_len;
1236
 
        else
1237
 
                store_ptr = storage;
1238
 
        nstored = net_len;
1239
 
        if (nstored > len) {
1240
 
                memcpy(buf, store_ptr, len);
1241
 
                nreturned += len;
1242
 
                store_ptr += len;
1243
 
                nstored -= len;
1244
 
        } else {
1245
 
                memcpy(buf, store_ptr, nstored);
1246
 
                nreturned += nstored;
1247
 
                nstored = 0;
1248
 
        }
1249
 
        
1250
 
        return(nreturned);
1251
 
}
1252
 
 
1253
 
static int
1254
 
v4_des_write(fd, buf, len, secondary)
1255
 
int fd;
1256
 
char *buf;
1257
 
size_t len;
1258
 
int secondary;
1259
 
{
1260
 
        static char garbage_buf[8];
1261
 
        unsigned char *len_buf = (unsigned char *) des_outpkt;
1262
 
 
1263
 
        /* 
1264
 
         * pcbc_encrypt outputs in 8-byte (64 bit) increments
1265
 
         *
1266
 
         * it zero-fills the cleartext to 8-byte padding,
1267
 
         * so if we have cleartext of < 8 bytes, we want
1268
 
         * to insert random garbage before it so that the ciphertext
1269
 
         * differs for each transmission of the same cleartext.
1270
 
         * if len < 8 - sizeof(long), sizeof(long) bytes of random
1271
 
         * garbage should be sufficient; leave the rest as-is in the buffer.
1272
 
         * if len > 8 - sizeof(long), just garbage fill the rest.
1273
 
         */
1274
 
 
1275
 
#ifdef min
1276
 
#undef min
1277
 
#endif
1278
 
#define min(a,b) ((a < b) ? a : b)
1279
 
 
1280
 
        if (len < 8) {
1281
 
                if (right_justify) {
1282
 
                        krb5_random_confounder(8 - len, garbage_buf);
1283
 
                        /* this "right-justifies" the data in the buffer */
1284
 
                        (void) memcpy(garbage_buf + 8 - len, buf, len);
1285
 
                } else {
1286
 
                        krb5_random_confounder(8 - len, garbage_buf + len);
1287
 
                        (void) memcpy(garbage_buf, buf, len);
1288
 
                }
1289
 
        }
1290
 
        (void) pcbc_encrypt((des_cblock *) ((len < 8) ? garbage_buf : buf),
1291
 
                            (des_cblock *) (des_outpkt+4),
1292
 
                            (int) ((len < 8) ? 8 : len),
1293
 
                            v4_schedule,
1294
 
                            &v4_session,
1295
 
                            ENCRYPT);
1296
 
 
1297
 
        /* tell the other end the real amount, but send an 8-byte padded
1298
 
           packet */
1299
 
        len_buf[0] = (len & 0xff000000) >> 24;
1300
 
        len_buf[1] = (len & 0xff0000) >> 16;
1301
 
        len_buf[2] = (len & 0xff00) >> 8;
1302
 
        len_buf[3] = (len & 0xff);
1303
 
        if (write(fd, des_outpkt, roundup(len,8)+4) != roundup(len,8)+4) {
1304
 
                errno = EIO;
1305
 
                return(-1);
1306
 
        }
1307
 
        return(len);
1308
 
}
1309
 
 
1310
 
#endif /* KRB5_KRB4_COMPAT */
1311
 
 
1312
983
#ifndef HAVE_STRSAVE
1313
984
/* Strsave was a routine in the version 4 krb library: we put it here
1314
985
   for compatablilty with version 5 krb library, since kcmd.o is linked
1320
991
{
1321
992
    register char *ret;
1322
993
    
1323
 
    if((ret = (char *) malloc((unsigned) strlen(sp)+1)) == NULL) {
 
994
    if((ret = strdup(sp)) == NULL) {
1324
995
        fprintf(stderr, "no memory for saving args\n");
1325
996
        exit(1);
1326
997
    }
1327
 
    (void) strcpy(ret,sp);
1328
998
    return(ret);
1329
999
}
1330
1000
#endif
1348
1018
     krb5_principal principal;
1349
1019
{
1350
1020
    char *def_realm;
1351
 
    unsigned int realm_length;
1352
1021
    int retval;
1353
1022
    
1354
 
    realm_length = krb5_princ_realm(bsd_context, principal)->length;
1355
 
    
1356
1023
    if ((retval = krb5_get_default_realm(bsd_context, &def_realm))) {
1357
1024
        return 0;
1358
1025
    }
1359
 
    
1360
 
    if ((realm_length != strlen(def_realm)) ||
1361
 
        (memcmp(def_realm, krb5_princ_realm(bsd_context, principal)->data, 
1362
 
                realm_length))) {
 
1026
 
 
1027
    if (!data_eq_string(*krb5_princ_realm(bsd_context, principal),
 
1028
                        def_realm)) {
1363
1029
        free(def_realm);
1364
1030
        return 0;
1365
1031
    }   
1366
1032
    free(def_realm);
1367
1033
    return 1;
1368
1034
}
1369