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