kernel: fq_codel: dont reinit flow state
[openwrt/staging/chunkeey.git] / 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
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 }