Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
[jra/samba/.git] / source / 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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21
22 #ifdef WITH_FAKE_KASERVER
23
24 #define NO_ASN1_TYPEDEFS 1
25
26 #include <afs/stds.h>
27 #include <afs/afs.h>
28 #include <afs/auth.h>
29 #include <afs/venus.h>
30 #include <asm/unistd.h>
31 #include <openssl/des.h>
32 #include <sys/syscall.h>
33
34 int afs_syscall( int subcall,
35           char * path,
36           int cmd,
37           char * cmarg,
38           int follow)
39 {
40         return( syscall( SYS_afs_syscall, subcall, path, cmd, cmarg, follow));
41 }
42
43 struct ClearToken {
44         uint32 AuthHandle;
45         char HandShakeKey[8];
46         uint32 ViceId;
47         uint32 BeginTimestamp;
48         uint32 EndTimestamp;
49 };
50
51 static bool afs_decode_token(const char *string, char **cell,
52                              DATA_BLOB *ticket, struct ClearToken *ct)
53 {
54         DATA_BLOB blob;
55         struct ClearToken result_ct;
56
57         char *s = SMB_STRDUP(string);
58
59         char *t;
60
61         if ((t = strtok(s, "\n")) == NULL) {
62                 DEBUG(10, ("strtok failed\n"));
63                 return False;
64         }
65
66         *cell = SMB_STRDUP(t);
67
68         if ((t = strtok(NULL, "\n")) == NULL) {
69                 DEBUG(10, ("strtok failed\n"));
70                 return False;
71         }
72
73         if (sscanf(t, "%u", &result_ct.AuthHandle) != 1) {
74                 DEBUG(10, ("sscanf AuthHandle failed\n"));
75                 return False;
76         }
77                 
78         if ((t = strtok(NULL, "\n")) == NULL) {
79                 DEBUG(10, ("strtok failed\n"));
80                 return False;
81         }
82
83         blob = base64_decode_data_blob(t);
84
85         if ( (blob.data == NULL) ||
86              (blob.length != sizeof(result_ct.HandShakeKey) )) {
87                 DEBUG(10, ("invalid key: %x/%d\n", (uint32)blob.data,
88                            blob.length));
89                 return False;
90         }
91
92         memcpy(result_ct.HandShakeKey, blob.data, blob.length);
93
94         data_blob_free(&blob);
95
96         if ((t = strtok(NULL, "\n")) == NULL) {
97                 DEBUG(10, ("strtok failed\n"));
98                 return False;
99         }
100
101         if (sscanf(t, "%u", &result_ct.ViceId) != 1) {
102                 DEBUG(10, ("sscanf ViceId failed\n"));
103                 return False;
104         }
105                 
106         if ((t = strtok(NULL, "\n")) == NULL) {
107                 DEBUG(10, ("strtok failed\n"));
108                 return False;
109         }
110
111         if (sscanf(t, "%u", &result_ct.BeginTimestamp) != 1) {
112                 DEBUG(10, ("sscanf BeginTimestamp failed\n"));
113                 return False;
114         }
115                 
116         if ((t = strtok(NULL, "\n")) == NULL) {
117                 DEBUG(10, ("strtok failed\n"));
118                 return False;
119         }
120
121         if (sscanf(t, "%u", &result_ct.EndTimestamp) != 1) {
122                 DEBUG(10, ("sscanf EndTimestamp failed\n"));
123                 return False;
124         }
125                 
126         if ((t = strtok(NULL, "\n")) == NULL) {
127                 DEBUG(10, ("strtok failed\n"));
128                 return False;
129         }
130
131         blob = base64_decode_data_blob(t);
132
133         if (blob.data == NULL) {
134                 DEBUG(10, ("Could not get ticket\n"));
135                 return False;
136         }
137
138         *ticket = blob;
139         *ct = result_ct;
140
141         return True;
142 }
143
144 /*
145   Put an AFS token into the Kernel so that it can authenticate against
146   the AFS server. This assumes correct local uid settings.
147
148   This is currently highly Linux and OpenAFS-specific. The correct API
149   call for this would be ktc_SetToken. But to do that we would have to
150   import a REALLY big bunch of libraries which I would currently like
151   to avoid. 
152 */
153
154 static bool afs_settoken(const char *cell,
155                          const struct ClearToken *ctok,
156                          DATA_BLOB ticket)
157 {
158         int ret;
159         struct {
160                 char *in, *out;
161                 uint16 in_size, out_size;
162         } iob;
163
164         char buf[1024];
165         char *p = buf;
166         int tmp;
167
168         memcpy(p, &ticket.length, sizeof(uint32));
169         p += sizeof(uint32);
170         memcpy(p, ticket.data, ticket.length);
171         p += ticket.length;
172
173         tmp = sizeof(struct ClearToken);
174         memcpy(p, &tmp, sizeof(uint32));
175         p += sizeof(uint32);
176         memcpy(p, ctok, tmp);
177         p += tmp;
178
179         tmp = 0;
180
181         memcpy(p, &tmp, sizeof(uint32));
182         p += sizeof(uint32);
183
184         tmp = strlen(cell);
185         if (tmp >= MAXKTCREALMLEN) {
186                 DEBUG(1, ("Realm too long\n"));
187                 return False;
188         }
189
190         strncpy(p, cell, tmp);
191         p += tmp;
192         *p = 0;
193         p +=1;
194
195         iob.in = buf;
196         iob.in_size = PTR_DIFF(p,buf);
197         iob.out = buf;
198         iob.out_size = sizeof(buf);
199
200 #if 0
201         file_save("/tmp/ioctlbuf", iob.in, iob.in_size);
202 #endif
203
204         ret = afs_syscall(AFSCALL_PIOCTL, 0, VIOCSETTOK, (char *)&iob, 0);
205
206         DEBUG(10, ("afs VIOCSETTOK returned %d\n", ret));
207         return (ret == 0);
208 }
209
210 bool afs_settoken_str(const char *token_string)
211 {
212         DATA_BLOB ticket;
213         struct ClearToken ct;
214         bool result;
215         char *cell;
216
217         if (!afs_decode_token(token_string, &cell, &ticket, &ct))
218                 return False;
219
220         if (geteuid() != 0)
221                 ct.ViceId = getuid();
222
223         result = afs_settoken(cell, &ct, ticket);
224
225         SAFE_FREE(cell);
226         data_blob_free(&ticket);
227
228         return result;
229 }
230
231 #else
232
233 bool afs_settoken_str(const char *token_string)
234 {
235         return False;
236 }
237
238 #endif