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