packages: sort network related packages into package/network/
[openwrt.git] / package / network / services / 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
22 passphrase.  pass can be NULL in which case the user is queried. */
23
24 int 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
142 int 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 }