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