Root/package/ead/src/tinysrp/tinysrp.c

1/* This bit implements a simple API for using the SRP library over sockets. */
2
3#include <stdio.h>
4#include <string.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <sys/types.h>
8#include <sys/socket.h>
9#include "t_defines.h"
10#include "t_pwd.h"
11#include "t_server.h"
12#include "t_client.h"
13#include "tinysrp.h"
14
15#ifndef MSG_WAITALL
16#ifdef linux
17#define MSG_WAITALL 0x100 /* somehow not defined on my box */
18#endif
19#endif
20
21/* This is called by the client with a connected socket, username, and
22passphrase. pass can be NULL in which case the user is queried. */
23
24int tsrp_client_authenticate(int s, char *user, char *pass, TSRP_SESSION *tsrp)
25{
26    int i, index;
27    unsigned char username[MAXUSERLEN + 1], sbuf[MAXSALTLEN];
28    unsigned char msgbuf[MAXPARAMLEN + 1], bbuf[MAXPARAMLEN];
29    unsigned char passbuf[128], *skey;
30    struct t_client *tc;
31    struct t_preconf *tcp; /* @@@ should go away */
32    struct t_num salt, *A, B;
33
34    /* Send the username. */
35
36    i = strlen(user);
37    if (i > MAXUSERLEN) {
38        i = MAXUSERLEN;
39    }
40    msgbuf[0] = i;
41    memcpy(msgbuf + 1, user, i);
42    if (send(s, msgbuf, i + 1, 0) < 0) {
43        return 0;
44    }
45    memcpy(username, user, i);
46    username[i] = '\0';
47
48    /* Get the prime index and salt. */
49
50    i = recv(s, msgbuf, 2, MSG_WAITALL);
51    if (i <= 0) {
52        return 0;
53    }
54    index = msgbuf[0];
55    if (index <= 0 || index > t_getprecount()) {
56        return 0;
57    }
58    tcp = t_getpreparam(index - 1);
59    salt.len = msgbuf[1];
60    if (salt.len > MAXSALTLEN) {
61        return 0;
62    }
63    salt.data = sbuf;
64    i = recv(s, sbuf, salt.len, MSG_WAITALL);
65    if (i <= 0) {
66        return 0;
67    }
68
69    /* @@@ t_clientopen() needs a variant that takes the index */
70
71    tc = t_clientopen(username, &tcp->modulus, &tcp->generator, &salt);
72    if (tc == NULL) {
73        return 0;
74    }
75
76    /* Calculate A and send it to the server. */
77
78    A = t_clientgenexp(tc);
79    msgbuf[0] = A->len - 1; /* len is max 256 */
80    memcpy(msgbuf + 1, A->data, A->len);
81    if (send(s, msgbuf, A->len + 1, 0) < 0) {
82        return 0;
83    }
84
85    /* Ask the user for the passphrase. */
86
87    if (pass == NULL) {
88        t_getpass(passbuf, sizeof(passbuf), "Enter password:");
89        pass = passbuf;
90    }
91    t_clientpasswd(tc, pass);
92
93    /* Get B from the server. */
94
95    i = recv(s, msgbuf, 1, 0);
96    if (i <= 0) {
97        return 0;
98    }
99    B.len = msgbuf[0] + 1;
100    B.data = bbuf;
101    i = recv(s, bbuf, B.len, MSG_WAITALL);
102    if (i <= 0) {
103        return 0;
104    }
105
106    /* Compute the session key. */
107
108    skey = t_clientgetkey(tc, &B);
109    if (skey == NULL) {
110        return 0;
111    }
112
113    /* Send the response. */
114
115    if (send(s, t_clientresponse(tc), RESPONSE_LEN, 0) < 0) {
116        return 0;
117    }
118
119    /* Get the server's response. */
120
121    i = recv(s, msgbuf, RESPONSE_LEN, MSG_WAITALL);
122    if (i <= 0) {
123        return 0;
124    }
125    if (t_clientverify(tc, msgbuf) != 0) {
126        return 0;
127    }
128
129    /* All done. Now copy the key and clean up. */
130
131    if (tsrp) {
132        memcpy(tsrp->username, username, strlen(username) + 1);
133        memcpy(tsrp->key, skey, SESSION_KEY_LEN);
134    }
135    t_clientclose(tc);
136
137    return 1;
138}
139
140/* This is called by the server with a connected socket. */
141
142int tsrp_server_authenticate(int s, TSRP_SESSION *tsrp)
143{
144    int i, j;
145    unsigned char username[MAXUSERLEN], *skey;
146    unsigned char msgbuf[MAXPARAMLEN + 1], abuf[MAXPARAMLEN];
147    struct t_server *ts;
148    struct t_num A, *B;
149
150    /* Get the username. */
151
152    i = recv(s, msgbuf, 1, 0);
153    if (i <= 0) {
154        return 0;
155    }
156    j = msgbuf[0];
157    i = recv(s, username, j, MSG_WAITALL);
158    if (i <= 0) {
159        return 0;
160    }
161    username[j] = '\0';
162
163    ts = t_serveropen(username);
164    if (ts == NULL) {
165        return 0;
166    }
167
168    /* Send the prime index and the salt. */
169
170    msgbuf[0] = ts->index; /* max 256 primes... */
171    i = ts->s.len;
172    msgbuf[1] = i;
173    memcpy(msgbuf + 2, ts->s.data, i);
174    if (send(s, msgbuf, i + 2, 0) < 0) {
175        return 0;
176    }
177
178    /* Calculate B while we're waiting. */
179
180    B = t_servergenexp(ts);
181
182    /* Get A from the client. */
183
184    i = recv(s, msgbuf, 1, 0);
185    if (i <= 0) {
186        return 0;
187    }
188    A.len = msgbuf[0] + 1;
189    A.data = abuf;
190    i = recv(s, abuf, A.len, MSG_WAITALL);
191    if (i <= 0) {
192        return 0;
193    }
194
195    /* Now send B. */
196
197    msgbuf[0] = B->len - 1;
198    memcpy(msgbuf + 1, B->data, B->len);
199    if (send(s, msgbuf, B->len + 1, 0) < 0) {
200        return 0;
201    }
202
203    /* Calculate the session key while we're waiting. */
204
205    skey = t_servergetkey(ts, &A);
206    if (skey == NULL) {
207        return 0;
208    }
209
210    /* Get the response from the client. */
211
212    i = recv(s, msgbuf, RESPONSE_LEN, MSG_WAITALL);
213    if (i <= 0) {
214        return 0;
215    }
216    if (t_serververify(ts, msgbuf) != 0) {
217        return 0;
218    }
219
220    /* Client authenticated. Now authenticate ourselves to the client. */
221
222    if (send(s, t_serverresponse(ts), RESPONSE_LEN, 0) < 0) {
223        return 0;
224    }
225
226    /* Copy the key and clean up. */
227
228    if (tsrp) {
229        memcpy(tsrp->username, username, strlen(username) + 1);
230        memcpy(tsrp->key, skey, SESSION_KEY_LEN);
231    }
232    t_serverclose(ts);
233
234    return 1;
235}
236

Archive Download this file



interactive