1/* 2 * Unix SMB/CIFS implementation. 3 * Generate AFS tickets 4 * Copyright (C) Volker Lendecke 2003 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 2 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, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21#include "includes.h" 22 23#ifdef WITH_FAKE_KASERVER 24 25#include <afs/stds.h> 26#include <afs/afs.h> 27#include <afs/auth.h> 28#include <afs/venus.h> 29#include <asm/unistd.h> 30#include <openssl/des.h> 31 32_syscall5(int, afs_syscall, int, subcall, 33 char *, path, 34 int, cmd, 35 char *, cmarg, 36 int, follow); 37 38struct ClearToken { 39 uint32 AuthHandle; 40 char HandShakeKey[8]; 41 uint32 ViceId; 42 uint32 BeginTimestamp; 43 uint32 EndTimestamp; 44}; 45 46/* 47 Put an AFS token into the Kernel so that it can authenticate against 48 the AFS server. This assumes correct local uid settings. 49 50 This is currently highly Linux and OpenAFS-specific. The correct API 51 call for this would be ktc_SetToken. But to do that we would have to 52 import a REALLY big bunch of libraries which I would currently like 53 to avoid. 54*/ 55 56static BOOL afs_settoken(const char *username, const char *cell, 57 const struct ClearToken *ctok, 58 char *v4tkt_data, int v4tkt_length) 59{ 60 int ret; 61 struct { 62 char *in, *out; 63 uint16 in_size, out_size; 64 } iob; 65 66 char buf[1024]; 67 char *p = buf; 68 int tmp; 69 70 memcpy(p, &v4tkt_length, sizeof(uint32)); 71 p += sizeof(uint32); 72 memcpy(p, v4tkt_data, v4tkt_length); 73 p += v4tkt_length; 74 75 tmp = sizeof(struct ClearToken); 76 memcpy(p, &tmp, sizeof(uint32)); 77 p += sizeof(uint32); 78 memcpy(p, ctok, tmp); 79 p += tmp; 80 81 tmp = 0; 82 83 memcpy(p, &tmp, sizeof(uint32)); 84 p += sizeof(uint32); 85 86 tmp = strlen(cell); 87 if (tmp >= MAXKTCREALMLEN) { 88 DEBUG(1, ("Realm too long\n")); 89 return False; 90 } 91 92 strncpy(p, cell, tmp); 93 p += tmp; 94 *p = 0; 95 p +=1; 96 97 iob.in = buf; 98 iob.in_size = PTR_DIFF(p,buf); 99 iob.out = buf; 100 iob.out_size = sizeof(buf); 101 102#if 0 103 file_save("/tmp/ioctlbuf", iob.in, iob.in_size); 104#endif 105 106 ret = afs_syscall(AFSCALL_PIOCTL, 0, VIOCSETTOK, (char *)&iob, 0); 107 108 DEBUG(10, ("afs VIOCSETTOK returned %d\n", ret)); 109 return (ret == 0); 110} 111 112/* 113 This routine takes a radical approach completely defeating the 114 Kerberos idea of security and using AFS simply as an intelligent 115 file backend. Samba has persuaded itself somehow that the user is 116 actually correctly identified and then we create a ticket that the 117 AFS server hopefully accepts using its KeyFile that the admin has 118 kindly stored to our secrets.tdb. 119 120 Thanks to the book "Network Security -- PRIVATE Communication in a 121 PUBLIC World" by Charlie Kaufman, Radia Perlman and Mike Speciner 122 Kerberos 4 tickets are not really hard to construct. 123 124 For the comments "Alice" is the User to be auth'ed, and "Bob" is the 125 AFS server. */ 126 127BOOL afs_login(connection_struct *conn) 128{ 129 fstring ticket; 130 char *p = ticket; 131 uint32 len; 132 struct afs_key key; 133 pstring afs_username; 134 char *cell; 135 136 struct ClearToken ct; 137 138 uint32 now; /* I assume time() returns 32 bit */ 139 140 des_key_schedule key_schedule; 141 142 pstrcpy(afs_username, lp_afs_username_map()); 143 standard_sub_conn(conn, afs_username, sizeof(afs_username)); 144 145 /* The pts command always generates completely lower-case user 146 * names. */ 147 strlower_m(afs_username); 148 149 cell = strchr(afs_username, '@'); 150 151 if (cell == NULL) { 152 DEBUG(1, ("AFS username doesn't contain a @, " 153 "could not find cell\n")); 154 return False; 155 } 156 157 *cell = '\0'; 158 cell += 1; 159 160 DEBUG(10, ("Trying to log into AFS for user %s@%s\n", 161 afs_username, cell)); 162 163 if (!secrets_init()) 164 return False; 165 166 if (!secrets_fetch_afs_key(cell, &key)) { 167 DEBUG(5, ("Could not fetch AFS service key\n")); 168 return False; 169 } 170 171 ct.AuthHandle = key.kvno; 172 173 /* Build the ticket. This is going to be encrypted, so in our 174 way we fill in ct while we still have the unencrypted 175 form. */ 176 177 p = ticket; 178 179 /* The byte-order */ 180 *p = 1; 181 p += 1; 182 183 /* "Alice", the client username */ 184 strncpy(p, afs_username, sizeof(ticket)-PTR_DIFF(p,ticket)-1); 185 p += strlen(p)+1; 186 strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1); 187 p += strlen(p)+1; 188 strncpy(p, cell, sizeof(ticket)-PTR_DIFF(p,ticket)-1); 189 p += strlen(p)+1; 190 191 /* This assumes that we have setresuid and set the real uid as well as 192 the effective uid in set_effective_uid(). */ 193 ct.ViceId = getuid(); 194 DEBUG(10, ("Creating Token for uid %d\n", ct.ViceId)); 195 196 /* Alice's network layer address. At least Openafs-1.2.10 197 ignores this, so we fill in a dummy value here. */ 198 SIVAL(p, 0, 0); 199 p += 4; 200 201 /* We need to create a session key */ 202 generate_random_buffer(p, 8, False); 203 204 /* Our client code needs the the key in the clear, it does not 205 know the server-key ... */ 206 memcpy(ct.HandShakeKey, p, 8); 207 208 p += 8; 209 210 /* Ticket lifetime. We fake everything here, so go as long as 211 possible. This is in 5-minute intervals, so 255 is 21 hours 212 and 15 minutes.*/ 213 *p = 255; 214 p += 1; 215 216 /* Ticket creation time */ 217 now = time(NULL); 218 SIVAL(p, 0, now); 219 ct.BeginTimestamp = now; 220 221 ct.EndTimestamp = now + (255*60*5); 222 if (((ct.EndTimestamp - ct.BeginTimestamp) & 1) == 1) { 223 ct.BeginTimestamp += 1; /* Lifetime must be even */ 224 } 225 p += 4; 226 227 /* And here comes Bob's name and instance, in this case the 228 AFS server. */ 229 strncpy(p, "afs", sizeof(ticket)-PTR_DIFF(p,ticket)-1); 230 p += strlen(p)+1; 231 strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1); 232 p += strlen(p)+1; 233 234 /* And zero-pad to a multiple of 8 bytes */ 235 len = PTR_DIFF(p, ticket); 236 if (len & 7) { 237 uint32 extra_space = 8-(len & 7); 238 memset(p, 0, extra_space); 239 p+=extra_space; 240 } 241 len = PTR_DIFF(p, ticket); 242 243 des_key_sched((const_des_cblock *)key.key, key_schedule); 244 des_pcbc_encrypt(ticket, ticket, 245 len, key_schedule, (C_Block *)key.key, 1); 246 247 ZERO_STRUCT(key); 248 249 return afs_settoken(afs_username, cell, &ct, ticket, len); 250} 251 252#else 253 254BOOL afs_login(connection_struct *conn) 255{ 256 return True; 257} 258 259#endif /* WITH_FAKE_KASERVER */ 260