Annotation of src/usr.bin/ssh/auth-krb4.c, Revision 1.1
1.1 ! deraadt 1: /*
! 2:
! 3: auth-kerberos.c
! 4:
! 5: Hacked together by Dug Song <dugsong@umich.edu>.
! 6:
! 7: Kerberos authentication and ticket-passing routines.
! 8:
! 9: */
! 10:
! 11: #include "includes.h"
! 12: #include "packet.h"
! 13: #include "xmalloc.h"
! 14: #include "ssh.h"
! 15:
! 16: #ifdef KRB4
! 17: #include <sys/param.h>
! 18: #include <krb.h>
! 19:
! 20: int ssh_tf_init(uid_t uid)
! 21: {
! 22: extern char *ticket;
! 23: char *tkt_root = TKT_ROOT;
! 24: struct stat st;
! 25: int fd;
! 26:
! 27: /* Set unique ticket string manually since we're still root. */
! 28: ticket = xmalloc(MAXPATHLEN);
! 29: #ifdef AFS
! 30: if (lstat("/ticket", &st) != -1)
! 31: tkt_root = "/ticket/";
! 32: #endif /* AFS */
! 33: sprintf(ticket, "%.100s%d_%d", tkt_root, uid, getpid());
! 34: (void) krb_set_tkt_string(ticket);
! 35:
! 36: /* Make sure we own this ticket file, and we created it. */
! 37: if (lstat(ticket, &st) < 0 && errno == ENOENT) {
! 38: /* good, no ticket file exists. create it. */
! 39: if ((fd = open(ticket, O_RDWR|O_CREAT|O_EXCL, 0600)) != -1) {
! 40: close(fd);
! 41: return 1;
! 42: }
! 43: }
! 44: else {
! 45: /* file exists. make sure server_user owns it (e.g. just passed ticket),
! 46: and that it isn't a symlink, and that it is mode 600. */
! 47: if (st.st_mode == (S_IFREG|S_IRUSR|S_IWUSR) && st.st_uid == uid)
! 48: return 1;
! 49: }
! 50: /* Failure. */
! 51: log("WARNING: bad ticket file %.100s", ticket);
! 52: return 0;
! 53: }
! 54:
! 55: int auth_krb4(const char *server_user, KTEXT auth, char **client)
! 56: {
! 57: AUTH_DAT adat = { 0 };
! 58: KTEXT_ST reply;
! 59: char instance[INST_SZ];
! 60: int r, s;
! 61: u_long cksum;
! 62: Key_schedule schedule;
! 63: struct sockaddr_in local, foreign;
! 64:
! 65: s = packet_get_connection_in();
! 66:
! 67: r = sizeof(local);
! 68: memset(&local, 0, sizeof(local));
! 69: if (getsockname(s, (struct sockaddr *) &local, &r) < 0)
! 70: debug("getsockname failed: %.100s", strerror(errno));
! 71: r = sizeof(foreign);
! 72: memset(&foreign, 0, sizeof(foreign));
! 73: if (getpeername(s, (struct sockaddr *)&foreign, &r) < 0)
! 74: debug("getpeername failed: %.100s", strerror(errno));
! 75:
! 76: instance[0] = '*'; instance[1] = 0;
! 77:
! 78: /* Get the encrypted request, challenge, and session key. */
! 79: r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, "");
! 80: if (r != KSUCCESS) {
! 81: packet_send_debug("Kerberos V4 krb_rd_req: %.100s", krb_err_txt[r]);
! 82: return 0;
! 83: }
! 84: des_key_sched((des_cblock *)adat.session, schedule);
! 85:
! 86: *client = xmalloc(MAX_K_NAME_SZ);
! 87: sprintf(*client, "%.100s%.100s%.100s@%.100s", adat.pname, *adat.pinst ? "." : "",
! 88: adat.pinst, adat.prealm);
! 89:
! 90: /* Check ~/.klogin authorization now. */
! 91: if (kuserok(&adat, (char *)server_user) != KSUCCESS) {
! 92: packet_send_debug("Kerberos V4 .klogin authorization failed!");
! 93: log("Kerberos V4 .klogin authorization failed for %.100s to account %.100s",
! 94: *client, server_user);
! 95: return 0;
! 96: }
! 97: /* Increment the checksum, and return it encrypted with the session key. */
! 98: cksum = adat.checksum + 1;
! 99: cksum = htonl(cksum);
! 100:
! 101: /* If we can't successfully encrypt the checksum, we send back an empty
! 102: message, admitting our failure. */
! 103: if ((r = krb_mk_priv((u_char *)&cksum, reply.dat, sizeof(cksum)+1,
! 104: schedule, &adat.session, &local, &foreign)) < 0) {
! 105: packet_send_debug("Kerberos V4 mk_priv: (%d) %.100s", r, krb_err_txt[r]);
! 106: reply.dat[0] = 0;
! 107: reply.length = 0;
! 108: }
! 109: else
! 110: reply.length = r;
! 111:
! 112: /* Clear session key. */
! 113: memset(&adat.session, 0, sizeof(&adat.session));
! 114:
! 115: packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
! 116: packet_put_string((char *) reply.dat, reply.length);
! 117: packet_send();
! 118: packet_write_wait();
! 119: return 1;
! 120: }
! 121: #endif /* KRB4 */
! 122:
! 123: #ifdef AFS
! 124: #include <kafs.h>
! 125:
! 126:
! 127: #ifdef KERBEROS_TGT_PASSING
! 128:
! 129: int auth_kerberos_tgt(struct passwd *pw, const char *string)
! 130: {
! 131: CREDENTIALS creds;
! 132: extern char *ticket;
! 133: int r;
! 134:
! 135: if (!radix_to_creds(string, &creds)) {
! 136: log("Protocol error decoding Kerberos V4 tgt");
! 137: packet_send_debug("Protocol error decoding Kerberos V4 tgt");
! 138: goto auth_kerberos_tgt_failure;
! 139: }
! 140: if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
! 141: strcpy(creds.service, "krbtgt");
! 142:
! 143: if (strcmp(creds.service, "krbtgt")) {
! 144: log("Kerberos V4 tgt (%.100s%.100s%.100s@%.100s) rejected for uid %d",
! 145: creds.pname, creds.pinst[0] ? "." : "", creds.pinst, creds.realm,
! 146: pw->pw_uid);
! 147: packet_send_debug("Kerberos V4 tgt (%.100s%.100s%.100s@%.100s) rejected for uid %d",
! 148: creds.pname, creds.pinst[0] ? "." : "", creds.pinst,
! 149: creds.realm, pw->pw_uid);
! 150: goto auth_kerberos_tgt_failure;
! 151: }
! 152: if (!ssh_tf_init(pw->pw_uid) ||
! 153: (r = in_tkt(creds.pname, creds.pinst)) ||
! 154: (r = save_credentials(creds.service,creds.instance,creds.realm,
! 155: creds.session,creds.lifetime,creds.kvno,
! 156: &creds.ticket_st,creds.issue_date))) {
! 157: xfree(ticket);
! 158: ticket = NULL;
! 159: packet_send_debug("Kerberos V4 tgt refused: couldn't save credentials");
! 160: goto auth_kerberos_tgt_failure;
! 161: }
! 162: /* Successful authentication, passed all checks. */
! 163: chown(ticket, pw->pw_uid, pw->pw_gid);
! 164: packet_send_debug("Kerberos V4 ticket accepted (%.100s.%.100s@%.100s, %.100s%.100s%.100s@%.100s)",
! 165: creds.service, creds.instance, creds.realm,
! 166: creds.pname, creds.pinst[0] ? "." : "",
! 167: creds.pinst, creds.realm);
! 168:
! 169: packet_start(SSH_SMSG_SUCCESS);
! 170: packet_send();
! 171: packet_write_wait();
! 172: return 1;
! 173:
! 174: auth_kerberos_tgt_failure:
! 175: memset(&creds, 0, sizeof(creds));
! 176: packet_start(SSH_SMSG_FAILURE);
! 177: packet_send();
! 178: packet_write_wait();
! 179: return 0;
! 180: }
! 181: #endif /* KERBEROS_TGT_PASSING */
! 182:
! 183: int auth_afs_token(char *server_user, uid_t uid, const char *string)
! 184: {
! 185: CREDENTIALS creds;
! 186:
! 187: if (!radix_to_creds(string, &creds)) {
! 188: log("Protocol error decoding AFS token");
! 189: packet_send_debug("Protocol error decoding AFS token");
! 190: packet_start(SSH_SMSG_FAILURE);
! 191: packet_send();
! 192: packet_write_wait();
! 193: return 0;
! 194: }
! 195: if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
! 196: strcpy(creds.service, "afs");
! 197:
! 198: if (strncmp(creds.pname, "AFS ID ", 7) == 0)
! 199: uid = atoi(creds.pname + 7);
! 200:
! 201: if (kafs_settoken(creds.realm, uid, &creds)) {
! 202: log("AFS token (%.100s@%.100s) rejected for uid %d",
! 203: creds.pname, creds.realm, uid);
! 204: packet_send_debug("AFS token (%.100s@%.100s) rejected for uid %d", creds.pname,
! 205: creds.realm, uid);
! 206: packet_start(SSH_SMSG_FAILURE);
! 207: packet_send();
! 208: packet_write_wait();
! 209: return 0;
! 210: }
! 211: packet_send_debug("AFS token accepted (%.100s@%.100s, %.100s@%.100s)", creds.service,
! 212: creds.realm, creds.pname, creds.realm);
! 213: packet_start(SSH_SMSG_SUCCESS);
! 214: packet_send();
! 215: packet_write_wait();
! 216: return 1;
! 217: }
! 218: #endif /* AFS */