source: roaraudio/libroar/auth.c @ 4473:8999323c97a8

Last change on this file since 4473:8999323c97a8 was 4473:8999323c97a8, checked in by phi, 14 years ago

test for positive auth

File size: 9.0 KB
Line 
1//auth.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illegal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38/* How auth works:
39 * 0) set stage to zero
40 * 1) get server address and local node name (from uname())
41 * 2) look up authfile/authdb/authservice for the server+local address + stage.
42 *    if no data was found send NONE-Auth.
43 * 3) send data to server
44 * 4) read answer from server
45 * 5) if stage of server response is non-zero increment stage to server stage+1
46 *    and repeat from step 2)
47 * 6) check if we got an OK or an ERROR, return correct value
48 */
49
50/* The protocol:
51 * Auth request:
52 * Byte 0: auth type
53 * Byte 1: stage
54 * Byte 2: reserved (must be zero)
55 * Byte 3: reserved (must be zero)
56 * Byte 4-end: auth type depending data.
57 *
58 * If no data is to be send bytes 2 and 3 can be omitted.
59 * If no data is to be send and stage is zero bytes 1, 2 and 3 can be omitted.
60 *
61 * Auth response:
62 * The same as the auth request.
63 * if the server sends an zero size message back it means the server accepted our connection
64 * and no additional stage is needed.
65 * if the message type is OK the server accepted our auth.
66 * if the message type is ERROR the server rejected us. we may try other auth methods.
67 * if the server accepted our data and the stage is non-zero we need to continue with the next
68 * stage of the auth.
69 * if the server rejected us the auth type value of the response is a suggested next auth type
70 * we should try if possible. This may help the client to find a working auth type.
71 */
72
73/* The protocol by auth type:
74 *
75 * --- NONE:
76 * No data is send, the server accepts the connect or rejects it depending on some
77 * magic within the server. we do not care about this.
78 * The data block is not used.
79 *
80 * --- COOKIE:
81 * We send cookies for all stages the server ask us to provide a cookie.
82 * if a cookie is wrong the server rejects us or asks us for another.
83 * The cookie is send as binary data in the data block.
84 *
85 * --- TRUST:
86 * We ask the server to auth us based on our UID/GID/PID.
87 * The server may reject this because we are not allowed or because it is not
88 * supported by the transport.
89 * If we get rejected we may try to continue with IDENT then RHOST before we use NONE.
90 * The data block is not used.
91 *
92 * --- PASSWORD:
93 * This is technically the same as COOKIE just that the cookie is limited to
94 * printable ASCII chars and that the user should be asked to provide the password.
95 * This may be done via a GUI popup window.
96 *
97 * --- SYSUSER:
98 * We provide a Username + Password for a system user.
99 * The data block contains of two main parts:
100 * The first part is a one byte long subtype.
101 * The value must be 0x01 for username+password.
102 * future versions may define other types.
103 * the second part is the actual data block.
104 * for username+password it is splited into two fields, both terminated with \0.
105 * the first is the username the last one the password as clear text.
106 * Example: char data[] = "\001MyUser\0MyPassword\0";
107 *
108 * --- OPENPGP_SIGN:
109 *
110 * --- OPENPGP_ENCRYPT:
111 *
112 * --- OPENPGP_AUTH:
113 *
114 * --- KERBEROS:
115 * We use Kerberos to auth.
116 *
117 * --- RHOST:
118 * The server is asked to auth us based on our source address.
119 * The data block is not used.
120 *
121 * --- XAUTH:
122 * We send an X11 Cookie.
123 *
124 * --- IDENT:
125 * The server is asked to auth us based on our source address using the IDENT protocol.
126 * The data block is not used.
127 *
128 */
129
130static int roar_auth_ask_server (struct roar_connection * con, struct roar_auth_message * authmes) {
131 struct roar_message   mes;
132 char                * header = mes.data;
133 int                   ret;
134
135 memset(&mes, 0, sizeof(struct roar_message)); // make valgrind happy!
136
137 mes.cmd     = ROAR_CMD_AUTH;
138 mes.datalen = 4;
139
140 header[0] = authmes->type;
141 header[1] = authmes->stage;
142 header[2] = authmes->reserved.c[0];
143 header[3] = authmes->reserved.c[1];
144
145 if ( (ret = roar_req(con, &mes, NULL)) == -1 )
146  return -1;
147
148 if ( mes.cmd != ROAR_CMD_OK )
149  return -1;
150
151 if ( mes.datalen < 4 ) {
152  memset(header+mes.datalen, 0, 4-mes.datalen);
153 }
154
155 authmes->type          = header[0];
156 authmes->stage         = header[1];
157 authmes->reserved.c[0] = header[2];
158 authmes->reserved.c[1] = header[3];
159
160 return 0;
161}
162
163static void roar_auth_mes_init(struct roar_auth_message * authmes, int type) {
164 memset(authmes, 0, sizeof(struct roar_auth_message));
165
166 authmes->type  = type;
167 authmes->stage = 0;
168 authmes->data  = NULL;
169 authmes->len   = 0;
170}
171
172#define _EOL ROAR_AUTH_T_AUTO
173int roar_auth   (struct roar_connection * con) {
174 struct roar_auth_message authmes;
175 int ret;
176 int i;
177 int ltt[] = {
178              ROAR_AUTH_T_TRUST,
179              ROAR_AUTH_T_IDENT,
180              ROAR_AUTH_T_RHOST,
181              ROAR_AUTH_T_NONE,
182              _EOL
183             };
184
185 for (i = 0; ltt[i] != _EOL; i++) {
186  roar_auth_mes_init(&authmes, ltt[i]);
187
188  if ( (ret = roar_auth_ask_server(con, &authmes)) == -1 )
189   continue;
190
191  if ( authmes.stage != 0 )
192   continue;
193
194  return 0;
195 }
196
197 return -1;
198}
199
200
201int roar_auth_from_mes(struct roar_auth_message * ames, struct roar_message * mes, void * data) {
202 void * ibuf;
203 char header[4] = {0, 0, 0, 0};
204
205 if ( ames == NULL || mes == NULL )
206  return -1;
207
208 if ( data != NULL ) {
209  ibuf = data;
210 } else {
211  ibuf = mes->data;
212 }
213
214 memset(ames, 0, sizeof(struct roar_auth_message));
215
216 memcpy(header, ibuf, mes->datalen < 4 ? mes->datalen : 4);
217
218 ames->type          = header[0];
219 ames->stage         = header[1];
220 ames->reserved.c[0] = header[2];
221 ames->reserved.c[1] = header[3];
222
223 if ( mes->datalen > 4 ) {
224  ames->data = ibuf + 4;
225  ames->len  = mes->datalen - 4;
226 } else {
227  ames->data = NULL;
228  ames->len  = 0;
229 }
230
231 return 0;
232}
233
234int roar_auth_to_mes(struct roar_message * mes, void ** data, struct roar_auth_message * ames) {
235 char * obuf;
236
237 if ( mes == NULL || ames == NULL )
238  return -1;
239
240 if ( data != NULL )
241  *data = NULL;
242
243 memset(mes, 0, sizeof(struct roar_message));
244
245 if ( (ames->len + 4) > sizeof(mes->data) ) {
246  *data = malloc(ames->len + 4);
247  if ( *data == NULL )
248   return -1;
249  obuf = *data;
250 } else {
251  obuf = mes->data;
252 }
253
254 obuf[0] = ames->type;
255 obuf[1] = ames->stage;
256 obuf[2] = ames->reserved.c[0];
257 obuf[3] = ames->reserved.c[1];
258
259 memcpy(obuf + 8, ames->data, ames->len);
260
261 mes->datalen = ames->len + 4;
262
263 return 0;
264}
265
266int roar_auth_init_mes(struct roar_message * mes, struct roar_auth_message * ames) {
267 if ( mes == NULL || ames == NULL )
268  return -1;
269
270 if ( (ames->len + 4) > sizeof(mes->data) )
271  return -1;
272
273 memset(mes, 0, sizeof(struct roar_message));
274
275 mes->data[0] = ames->type;
276 mes->data[1] = ames->stage;
277 mes->data[2] = ames->reserved.c[0];
278 mes->data[3] = ames->reserved.c[1];
279
280 ames->data = &(mes->data[4]);
281
282 mes->datalen = ames->len + 4;
283
284 return 0;
285}
286
287
288
289// String functions:
290static struct {
291 int    type;
292 const char * name;
293} _g_authts[] = {
294// grep ^'#define ROAR_AUTH_T_' auth.h | while read d t d; do n=$(cut -d_ -f4 <<<$t | tr A-Z a-z); printf ' {%-28s %-10s},\n' $t, \"$n\"; done
295 {ROAR_AUTH_T_NONE,            "none"    },
296 {ROAR_AUTH_T_COOKIE,          "cookie"  },
297 {ROAR_AUTH_T_TRUST,           "trust"   },
298 {ROAR_AUTH_T_PASSWORD,        "password"},
299 {ROAR_AUTH_T_SYSUSER,         "sysuser" },
300 {ROAR_AUTH_T_OPENPGP_SIGN,    "openpgp" },
301 {ROAR_AUTH_T_OPENPGP_ENCRYPT, "openpgp" },
302 {ROAR_AUTH_T_OPENPGP_AUTH,    "openpgp" },
303 {ROAR_AUTH_T_KERBEROS,        "kerberos"},
304 {ROAR_AUTH_T_RHOST,           "rhost"   },
305 {ROAR_AUTH_T_XAUTH,           "xauth"   },
306 {ROAR_AUTH_T_IDENT,           "ident"   },
307 {-1, NULL}
308};
309
310int    roar_str2autht(const char * str) {
311 int i;
312
313 for (i = 0; _g_authts[i].name != NULL; i++)
314  if ( !strcasecmp(_g_authts[i].name, str) )
315   return _g_authts[i].type;
316
317 return -1;
318}
319
320const char * roar_autht2str(const int auth) {
321 int i;
322
323 for (i = 0; _g_authts[i].name != NULL; i++)
324  if ( _g_authts[i].type == auth )
325   return _g_authts[i].name;
326
327 return "(UNKNOWN)";
328}
329
330//ll
Note: See TracBrowser for help on using the repository browser.