r449: Two AFS-related things:
[jra/samba/.git] / source3 / lib / afs_settoken.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Generate AFS tickets
4  *  Copyright (C) Volker Lendecke 2004
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "includes.h"
22
23 #ifdef WITH_FAKE_KASERVER
24
25 #include <afs/stds.h>
26 #include <afs/afs.h>
27 #include <afs/auth.h>
28 #include <afs/venus.h>
29 #include <asm/unistd.h>
30 #include <openssl/des.h>
31
32 _syscall5(int, afs_syscall, int, subcall,
33           char *, path,
34           int, cmd,
35           char *, cmarg,
36           int, follow);
37
38 struct ClearToken {
39         uint32 AuthHandle;
40         char HandShakeKey[8];
41         uint32 ViceId;
42         uint32 BeginTimestamp;
43         uint32 EndTimestamp;
44 };
45
46 static BOOL afs_decode_token(const char *string, char **cell,
47                              DATA_BLOB *ticket, struct ClearToken *ct)
48 {
49         DATA_BLOB blob;
50         struct ClearToken result_ct;
51
52         char *s = strdup(string);
53
54         char *t;
55
56         if ((t = strtok(s, "\n")) == NULL) {
57                 DEBUG(10, ("strtok failed\n"));
58                 return False;
59         }
60
61         *cell = strdup(t);
62
63         if ((t = strtok(NULL, "\n")) == NULL) {
64                 DEBUG(10, ("strtok failed\n"));
65                 return False;
66         }
67
68         if (sscanf(t, "%u", &result_ct.AuthHandle) != 1) {
69                 DEBUG(10, ("sscanf AuthHandle failed\n"));
70                 return False;
71         }
72                 
73         if ((t = strtok(NULL, "\n")) == NULL) {
74                 DEBUG(10, ("strtok failed\n"));
75                 return False;
76         }
77
78         blob = base64_decode_data_blob(t);
79
80         if ( (blob.data == NULL) ||
81              (blob.length != sizeof(result_ct.HandShakeKey) )) {
82                 DEBUG(10, ("invalid key: %x/%d\n", (uint32)blob.data,
83                            blob.length));
84                 return False;
85         }
86
87         memcpy(result_ct.HandShakeKey, blob.data, blob.length);
88
89         data_blob_free(&blob);
90
91         if ((t = strtok(NULL, "\n")) == NULL) {
92                 DEBUG(10, ("strtok failed\n"));
93                 return False;
94         }
95
96         if (sscanf(t, "%u", &result_ct.ViceId) != 1) {
97                 DEBUG(10, ("sscanf ViceId failed\n"));
98                 return False;
99         }
100                 
101         if ((t = strtok(NULL, "\n")) == NULL) {
102                 DEBUG(10, ("strtok failed\n"));
103                 return False;
104         }
105
106         if (sscanf(t, "%u", &result_ct.BeginTimestamp) != 1) {
107                 DEBUG(10, ("sscanf BeginTimestamp failed\n"));
108                 return False;
109         }
110                 
111         if ((t = strtok(NULL, "\n")) == NULL) {
112                 DEBUG(10, ("strtok failed\n"));
113                 return False;
114         }
115
116         if (sscanf(t, "%u", &result_ct.EndTimestamp) != 1) {
117                 DEBUG(10, ("sscanf EndTimestamp failed\n"));
118                 return False;
119         }
120                 
121         if ((t = strtok(NULL, "\n")) == NULL) {
122                 DEBUG(10, ("strtok failed\n"));
123                 return False;
124         }
125
126         blob = base64_decode_data_blob(t);
127
128         if (blob.data == NULL) {
129                 DEBUG(10, ("Could not get ticket\n"));
130                 return False;
131         }
132
133         *ticket = blob;
134         *ct = result_ct;
135
136         return True;
137 }
138
139 /*
140   Put an AFS token into the Kernel so that it can authenticate against
141   the AFS server. This assumes correct local uid settings.
142
143   This is currently highly Linux and OpenAFS-specific. The correct API
144   call for this would be ktc_SetToken. But to do that we would have to
145   import a REALLY big bunch of libraries which I would currently like
146   to avoid. 
147 */
148
149 static BOOL afs_settoken(const char *cell,
150                          const struct ClearToken *ctok,
151                          DATA_BLOB ticket)
152 {
153         int ret;
154         struct {
155                 char *in, *out;
156                 uint16 in_size, out_size;
157         } iob;
158
159         char buf[1024];
160         char *p = buf;
161         int tmp;
162
163         memcpy(p, &ticket.length, sizeof(uint32));
164         p += sizeof(uint32);
165         memcpy(p, ticket.data, ticket.length);
166         p += ticket.length;
167
168         tmp = sizeof(struct ClearToken);
169         memcpy(p, &tmp, sizeof(uint32));
170         p += sizeof(uint32);
171         memcpy(p, ctok, tmp);
172         p += tmp;
173
174         tmp = 0;
175
176         memcpy(p, &tmp, sizeof(uint32));
177         p += sizeof(uint32);
178
179         tmp = strlen(cell);
180         if (tmp >= MAXKTCREALMLEN) {
181                 DEBUG(1, ("Realm too long\n"));
182                 return False;
183         }
184
185         strncpy(p, cell, tmp);
186         p += tmp;
187         *p = 0;
188         p +=1;
189
190         iob.in = buf;
191         iob.in_size = PTR_DIFF(p,buf);
192         iob.out = buf;
193         iob.out_size = sizeof(buf);
194
195 #if 0
196         file_save("/tmp/ioctlbuf", iob.in, iob.in_size);
197 #endif
198
199         ret = afs_syscall(AFSCALL_PIOCTL, 0, VIOCSETTOK, (char *)&iob, 0);
200
201         DEBUG(10, ("afs VIOCSETTOK returned %d\n", ret));
202         return (ret == 0);
203 }
204
205 BOOL afs_settoken_str(const char *token_string)
206 {
207         DATA_BLOB ticket;
208         struct ClearToken ct;
209         BOOL result;
210         char *cell;
211
212         if (!afs_decode_token(token_string, &cell, &ticket, &ct))
213                 return False;
214
215         if (geteuid() != 0)
216                 ct.ViceId = getuid();
217
218         result = afs_settoken(cell, &ct, ticket);
219
220         SAFE_FREE(cell);
221         data_blob_free(&ticket);
222
223         return result;
224 }
225
226 #else
227
228 BOOL afs_settoken_str(const char *token_string)
229 {
230         return False;
231 }
232
233 #endif