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