I found lots of places where we assume error will be set when calling
[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 <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         char *saveptr;
57
58         char *s = SMB_STRDUP(string);
59
60         char *t;
61
62         if ((t = strtok_r(s, "\n", &saveptr)) == NULL) {
63                 DEBUG(10, ("strtok_r failed\n"));
64                 return False;
65         }
66
67         *cell = SMB_STRDUP(t);
68
69         if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
70                 DEBUG(10, ("strtok_r failed\n"));
71                 return False;
72         }
73
74         if (sscanf(t, "%u", &result_ct.AuthHandle) != 1) {
75                 DEBUG(10, ("sscanf AuthHandle failed\n"));
76                 return False;
77         }
78                 
79         if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
80                 DEBUG(10, ("strtok_r failed\n"));
81                 return False;
82         }
83
84         blob = base64_decode_data_blob(t);
85
86         if ( (blob.data == NULL) ||
87              (blob.length != sizeof(result_ct.HandShakeKey) )) {
88                 DEBUG(10, ("invalid key: %x/%d\n", (uint32)blob.data,
89                            blob.length));
90                 return False;
91         }
92
93         memcpy(result_ct.HandShakeKey, blob.data, blob.length);
94
95         data_blob_free(&blob);
96
97         if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
98                 DEBUG(10, ("strtok_r failed\n"));
99                 return False;
100         }
101
102         if (sscanf(t, "%u", &result_ct.ViceId) != 1) {
103                 DEBUG(10, ("sscanf ViceId failed\n"));
104                 return False;
105         }
106                 
107         if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
108                 DEBUG(10, ("strtok_r failed\n"));
109                 return False;
110         }
111
112         if (sscanf(t, "%u", &result_ct.BeginTimestamp) != 1) {
113                 DEBUG(10, ("sscanf BeginTimestamp failed\n"));
114                 return False;
115         }
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.EndTimestamp) != 1) {
123                 DEBUG(10, ("sscanf EndTimestamp 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         blob = base64_decode_data_blob(t);
133
134         if (blob.data == NULL) {
135                 DEBUG(10, ("Could not get ticket\n"));
136                 return False;
137         }
138
139         *ticket = blob;
140         *ct = result_ct;
141
142         return True;
143 }
144
145 /*
146   Put an AFS token into the Kernel so that it can authenticate against
147   the AFS server. This assumes correct local uid settings.
148
149   This is currently highly Linux and OpenAFS-specific. The correct API
150   call for this would be ktc_SetToken. But to do that we would have to
151   import a REALLY big bunch of libraries which I would currently like
152   to avoid. 
153 */
154
155 static bool afs_settoken(const char *cell,
156                          const struct ClearToken *ctok,
157                          DATA_BLOB ticket)
158 {
159         int ret;
160         struct {
161                 char *in, *out;
162                 uint16 in_size, out_size;
163         } iob;
164
165         char buf[1024];
166         char *p = buf;
167         int tmp;
168
169         memcpy(p, &ticket.length, sizeof(uint32));
170         p += sizeof(uint32);
171         memcpy(p, ticket.data, ticket.length);
172         p += ticket.length;
173
174         tmp = sizeof(struct ClearToken);
175         memcpy(p, &tmp, sizeof(uint32));
176         p += sizeof(uint32);
177         memcpy(p, ctok, tmp);
178         p += tmp;
179
180         tmp = 0;
181
182         memcpy(p, &tmp, sizeof(uint32));
183         p += sizeof(uint32);
184
185         tmp = strlen(cell);
186         if (tmp >= MAXKTCREALMLEN) {
187                 DEBUG(1, ("Realm too long\n"));
188                 return False;
189         }
190
191         strncpy(p, cell, tmp);
192         p += tmp;
193         *p = 0;
194         p +=1;
195
196         iob.in = buf;
197         iob.in_size = PTR_DIFF(p,buf);
198         iob.out = buf;
199         iob.out_size = sizeof(buf);
200
201 #if 0
202         file_save("/tmp/ioctlbuf", iob.in, iob.in_size);
203 #endif
204
205         ret = afs_syscall(AFSCALL_PIOCTL, 0, VIOCSETTOK, (char *)&iob, 0);
206
207         DEBUG(10, ("afs VIOCSETTOK returned %d\n", ret));
208         return (ret == 0);
209 }
210
211 bool afs_settoken_str(const char *token_string)
212 {
213         DATA_BLOB ticket;
214         struct ClearToken ct;
215         bool result;
216         char *cell;
217
218         if (!afs_decode_token(token_string, &cell, &ticket, &ct))
219                 return False;
220
221         if (geteuid() != 0)
222                 ct.ViceId = getuid();
223
224         result = afs_settoken(cell, &ct, ticket);
225
226         SAFE_FREE(cell);
227         data_blob_free(&ticket);
228
229         return result;
230 }
231
232 #else
233
234 bool afs_settoken_str(const char *token_string)
235 {
236         return False;
237 }
238
239 #endif