Annotation of src/usr.bin/ssh/auth-skey.c, Revision 1.7
1.1 markus 1: #include "includes.h"
1.7 ! markus 2: RCSID("$OpenBSD: auth-skey.c,v 1.6 2000/04/14 10:30:29 markus Exp $");
1.1 markus 3:
4: #include "ssh.h"
1.4 markus 5: #include "packet.h"
1.1 markus 6: #include <sha1.h>
7:
1.6 markus 8: /*
1.4 markus 9: * try skey authentication,
1.6 markus 10: * return 1 on success, 0 on failure, -1 if skey is not available
1.4 markus 11: */
12:
1.6 markus 13: int
1.4 markus 14: auth_skey_password(struct passwd * pw, const char *password)
15: {
16: if (strncasecmp(password, "s/key", 5) == 0) {
17: char *skeyinfo = skey_keyinfo(pw->pw_name);
18: if (skeyinfo == NULL) {
19: debug("generating fake skeyinfo for %.100s.",
20: pw->pw_name);
21: skeyinfo = skey_fake_keyinfo(pw->pw_name);
22: }
23: if (skeyinfo != NULL)
24: packet_send_debug(skeyinfo);
25: /* Try again. */
26: return 0;
27: } else if (skey_haskey(pw->pw_name) == 0 &&
28: skey_passcheck(pw->pw_name, (char *) password) != -1) {
29: /* Authentication succeeded. */
30: return 1;
31: }
32: /* Fall back to ordinary passwd authentication. */
33: return -1;
34: }
35:
1.1 markus 36: /* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
37:
38: #define ROUND(x) (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
39: ((x)[3]))
40:
41: /*
42: * hash_collapse()
43: */
44: static u_int32_t
45: hash_collapse(s)
1.6 markus 46: u_char *s;
1.1 markus 47: {
1.6 markus 48: int len, target;
1.1 markus 49: u_int32_t i;
50:
51: if ((strlen(s) % sizeof(u_int32_t)) == 0)
1.6 markus 52: target = strlen(s); /* Multiple of 4 */
1.1 markus 53: else
54: target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
1.6 markus 55:
1.1 markus 56: for (i = 0, len = 0; len < target; len += 4)
1.6 markus 57: i ^= ROUND(s + len);
1.1 markus 58:
59: return i;
60: }
1.3 markus 61:
1.1 markus 62: char *
63: skey_fake_keyinfo(char *username)
64: {
65: int i;
66: u_int ptr;
67: u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
68: char pbuf[SKEY_MAX_PW_LEN+1];
69: static char skeyprompt[SKEY_MAX_CHALLENGE+1];
70: char *secret = NULL;
71: size_t secretlen = 0;
72: SHA1_CTX ctx;
73: char *p, *u;
74:
75: /*
76: * Base first 4 chars of seed on hostname.
77: * Add some filler for short hostnames if necessary.
78: */
79: if (gethostname(pbuf, sizeof(pbuf)) == -1)
80: *(p = pbuf) = '.';
81: else
82: for (p = pbuf; *p && isalnum(*p); p++)
83: if (isalpha(*p) && isupper(*p))
84: *p = tolower(*p);
85: if (*p && pbuf - p < 4)
86: (void)strncpy(p, "asjd", 4 - (pbuf - p));
87: pbuf[4] = '\0';
88:
89: /* Hash the username if possible */
90: if ((up = SHA1Data(username, strlen(username), NULL)) != NULL) {
91: struct stat sb;
92: time_t t;
93: int fd;
94:
95: /* Collapse the hash */
96: ptr = hash_collapse(up);
97: memset(up, 0, strlen(up));
98:
99: /* See if the random file's there, else use ctime */
100: if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
101: && fstat(fd, &sb) == 0 &&
102: sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
103: lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
104: SEEK_SET) != -1 && read(fd, hseed,
105: SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
106: close(fd);
1.5 deraadt 107: fd = -1;
1.1 markus 108: secret = hseed;
109: secretlen = SKEY_MAX_SEED_LEN;
110: flg = 0;
111: } else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
112: t = sb.st_ctime;
113: secret = ctime(&t);
114: secretlen = strlen(secret);
115: flg = 0;
116: }
1.5 deraadt 117: if (fd != -1)
118: close(fd);
1.1 markus 119: }
120:
121: /* Put that in your pipe and smoke it */
122: if (flg == 0) {
123: /* Hash secret value with username */
124: SHA1Init(&ctx);
125: SHA1Update(&ctx, secret, secretlen);
126: SHA1Update(&ctx, username, strlen(username));
127: SHA1End(&ctx, up);
128:
129: /* Zero out */
130: memset(secret, 0, secretlen);
131:
132: /* Now hash the hash */
133: SHA1Init(&ctx);
134: SHA1Update(&ctx, up, strlen(up));
135: SHA1End(&ctx, up);
136:
137: ptr = hash_collapse(up + 4);
138:
139: for (i = 4; i < 9; i++) {
140: pbuf[i] = (ptr % 10) + '0';
141: ptr /= 10;
142: }
143: pbuf[i] = '\0';
144:
145: /* Sequence number */
146: ptr = ((up[2] + up[3]) % 99) + 1;
147:
148: memset(up, 0, 20); /* SHA1 specific */
149: free(up);
150:
1.2 deraadt 151: (void)snprintf(skeyprompt, sizeof skeyprompt,
1.1 markus 152: "otp-%.*s %d %.*s",
153: SKEY_MAX_HASHNAME_LEN,
154: skey_get_algorithm(),
155: ptr, SKEY_MAX_SEED_LEN,
156: pbuf);
157: } else {
158: /* Base last 8 chars of seed on username */
159: u = username;
160: i = 8;
161: p = &pbuf[4];
162: do {
163: if (*u == 0) {
164: /* Pad remainder with zeros */
165: while (--i >= 0)
166: *p++ = '0';
167: break;
168: }
169:
170: *p++ = (*u++ % 10) + '0';
171: } while (--i != 0);
172: pbuf[12] = '\0';
173:
1.2 deraadt 174: (void)snprintf(skeyprompt, sizeof skeyprompt,
175: "otp-%.*s %d %.*s",
1.1 markus 176: SKEY_MAX_HASHNAME_LEN,
177: skey_get_algorithm(),
178: 99, SKEY_MAX_SEED_LEN, pbuf);
179: }
180: return skeyprompt;
181: }