summaryrefslogtreecommitdiff
path: root/auth-krb4.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth-krb4.c')
-rw-r--r--auth-krb4.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/auth-krb4.c b/auth-krb4.c
new file mode 100644
index 000000000..720f3a4c4
--- /dev/null
+++ b/auth-krb4.c
@@ -0,0 +1,209 @@
1/*
2
3 auth-kerberos.c
4
5 Dug Song <dugsong@UMICH.EDU>
6
7 Kerberos v4 authentication and ticket-passing routines.
8
9 $Id: auth-krb4.c,v 1.1 1999/10/27 03:42:43 damien Exp $
10*/
11
12#include "includes.h"
13#include "packet.h"
14#include "xmalloc.h"
15#include "ssh.h"
16
17#ifdef KRB4
18int ssh_tf_init(uid_t uid)
19{
20 extern char *ticket;
21 char *tkt_root = TKT_ROOT;
22 struct stat st;
23 int fd;
24
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 */
31 snprintf(ticket, MAXPATHLEN, "%s%d_%d", tkt_root, uid, getpid());
32 (void) krb_set_tkt_string(ticket);
33
34 /* Make sure we own this ticket file, and we created it. */
35 if (lstat(ticket, &st) == -1 && errno == ENOENT) {
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. */
49 log("WARNING: bad ticket file %s", ticket);
50 return 0;
51}
52
53int 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_int 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. */
77 if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, ""))) {
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);
84 (void) snprintf(*client, MAX_K_NAME_SZ, "%s%s%s@%s", adat.pname,
85 *adat.pinst ? "." : "", adat.pinst, adat.prealm);
86
87 /* Check ~/.klogin authorization now. */
88 if (kuserok(&adat, (char *)server_user) != KSUCCESS) {
89 packet_send_debug("Kerberos V4 .klogin authorization failed!");
90 log("Kerberos V4 .klogin authorization failed for %s to account %s",
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) {
102 packet_send_debug("Kerberos V4 mk_priv: (%d) %s", r, krb_err_txt[r]);
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
121int 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 */
133 strlcpy(creds.service, "krbtgt", sizeof creds.service);
134
135 if (strcmp(creds.service, "krbtgt")) {
136 log("Kerberos V4 tgt (%s%s%s@%s) rejected for uid %d",
137 creds.pname, creds.pinst[0] ? "." : "", creds.pinst, creds.realm,
138 pw->pw_uid);
139 packet_send_debug("Kerberos V4 tgt (%s%s%s@%s) rejected for uid %d",
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)) ||
146 (r = save_credentials(creds.service, creds.instance, creds.realm,
147 creds.session, creds.lifetime, creds.kvno,
148 &creds.ticket_st, creds.issue_date))) {
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);
156 packet_send_debug("Kerberos V4 tgt accepted (%s.%s@%s, %s%s%s@%s)",
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
166auth_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
174int 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 */
187 strlcpy(creds.service, "afs", sizeof creds.service);
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)) {
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,
196 creds.realm, uid);
197 packet_start(SSH_SMSG_FAILURE);
198 packet_send();
199 packet_write_wait();
200 return 0;
201 }
202 packet_send_debug("AFS token accepted (%s@%s, %s@%s)", creds.service,
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 */