1implement Auth9; 2 3# 4# elements of Plan 9 authentication 5# 6# this is a near transliteration of Plan 9 source, subject to the Lucent Public License 1.02 7# 8 9include "sys.m"; 10 sys: Sys; 11 12include "ipints.m"; 13 14include "crypt.m"; 15 16include "auth9.m"; 17 18init() 19{ 20 sys = load Sys Sys->PATH; 21} 22 23put2(a: array of byte, v: int) 24{ 25 a[0] = byte v; 26 a[1] = byte (v>>8); 27} 28 29get2(a: array of byte): int 30{ 31 return (int a[1]<<8) | int a[0]; 32} 33 34put4(a: array of byte, v: int) 35{ 36 a[0] = byte v; 37 a[1] = byte (v>>8); 38 a[2] = byte (v>>16); 39 a[3] = byte (v>>24); 40} 41 42get4(a: array of byte): int 43{ 44 return (int a[3]<<24) | (int a[2]<<16) | (int a[1]<<8) | int a[0]; 45} 46 47puts(a: array of byte, s: string, n: int) 48{ 49 b := array of byte s; 50 l := len b; 51 if(l > n) 52 b = b[0:n]; 53 a[0:] = b; 54 for(; l < n; l++) 55 a[l] = byte 0; 56} 57 58gets(a: array of byte, n: int): string 59{ 60 for(i:=0; i<n; i++) 61 if(a[i] == byte 0) 62 break; 63 return string a[0:i]; 64} 65 66geta(a: array of byte, n: int): array of byte 67{ 68 b := array[n] of byte; 69 b[0:] = a[0:n]; 70 return b; 71} 72 73Authenticator.pack(f: self ref Authenticator, key: array of byte): array of byte 74{ 75 p := array[AUTHENTLEN] of {* => byte 0}; 76 p[0] = byte f.num; 77 p[1:] = f.chal; 78 put4(p[1+CHALLEN:], f.id); 79 if(key != nil) 80 encrypt(key, p, len p); 81 return p; 82} 83 84Authenticator.unpack(a: array of byte, key: array of byte): (int, ref Authenticator) 85{ 86 if(key != nil) 87 decrypt(key, a, AUTHENTLEN); 88 f := ref Authenticator; 89 f.num = int a[0]; 90 f.chal = geta(a[1:], CHALLEN); 91 f.id = get4(a[1+CHALLEN:]); 92 return (AUTHENTLEN, f); 93} 94 95Passwordreq.pack(f: self ref Passwordreq, key: array of byte): array of byte 96{ 97 a := array[PASSREQLEN] of {* => byte 0}; 98 a[0] = byte f.num; 99 a[1:] = f.old; 100 a[1+ANAMELEN:] = f.new; 101 a[1+2*ANAMELEN] = byte f.changesecret; 102 a[1+2*ANAMELEN+1:] = f.secret; 103 if(key != nil) 104 encrypt(key, a, len a); 105 return a; 106} 107 108Passwordreq.unpack(a: array of byte, key: array of byte): (int, ref Passwordreq) 109{ 110 if(key != nil) 111 decrypt(key, a, PASSREQLEN); 112 f := ref Passwordreq; 113 f.num = int a[0]; 114 f.old = geta(a[1:], ANAMELEN); 115 f.old[ANAMELEN-1] = byte 0; 116 f.new = geta(a[1+ANAMELEN:], ANAMELEN); 117 f.new[ANAMELEN-1] = byte 0; 118 f.changesecret = int a[1+2*ANAMELEN]; 119 f.secret = geta(a[1+2*ANAMELEN+1:], SECRETLEN); 120 f.secret[SECRETLEN-1] = byte 0; 121 return (PASSREQLEN, f); 122} 123 124Ticket.pack(f: self ref Ticket, key: array of byte): array of byte 125{ 126 a := array[TICKETLEN] of {* => byte 0}; 127 a[0] = byte f.num; 128 a[1:] = f.chal; 129 puts(a[1+CHALLEN:], f.cuid, ANAMELEN); 130 puts(a[1+CHALLEN+ANAMELEN:], f.suid, ANAMELEN); 131 a[1+CHALLEN+2*ANAMELEN:] = f.key; 132 if(key != nil) 133 encrypt(key, a, len a); 134 return a; 135} 136 137Ticket.unpack(a: array of byte, key: array of byte): (int, ref Ticket) 138{ 139 if(key != nil) 140 decrypt(key, a, TICKETLEN); 141 f := ref Ticket; 142 f.num = int a[0]; 143 f.chal = geta(a[1:], CHALLEN); 144 f.cuid = gets(a[1+CHALLEN:], ANAMELEN); 145 f.suid = gets(a[1+CHALLEN+ANAMELEN:], ANAMELEN); 146 f.key = geta(a[1+CHALLEN+2*ANAMELEN:], DESKEYLEN); 147 return (TICKETLEN, f); 148} 149 150Ticketreq.unpack(a: array of byte): (int, ref Ticketreq) 151{ 152 f := ref Ticketreq; 153 f.rtype = int a[0]; 154 f.authid = gets(a[1:], ANAMELEN); 155 f.authdom = gets(a[1+ANAMELEN:], DOMLEN); 156 f.chal = geta(a[1+ANAMELEN+DOMLEN:], CHALLEN); 157 f.hostid = gets(a[1+ANAMELEN+DOMLEN+CHALLEN:], ANAMELEN); 158 f.uid = gets(a[1+ANAMELEN+DOMLEN+CHALLEN+ANAMELEN:], ANAMELEN); 159 return (TICKREQLEN, f); 160} 161 162Ticketreq.pack(f: self ref Ticketreq): array of byte 163{ 164 a := array[TICKREQLEN] of {* => byte 0}; 165 a[0] = byte f.rtype; 166 puts(a[1:], f.authid, ANAMELEN); 167 puts(a[1+ANAMELEN:], f.authdom, DOMLEN); 168 a[1+ANAMELEN+DOMLEN:] = f.chal; 169 puts(a[1+ANAMELEN+DOMLEN+CHALLEN:], f.hostid, ANAMELEN); 170 puts(a[1+ANAMELEN+DOMLEN+CHALLEN+ANAMELEN:], f.uid, ANAMELEN); 171 return a; 172} 173 174netcrypt(key: array of byte, chal: string): string 175{ 176 buf := array[8] of {* => byte 0}; 177 a := array of byte chal; 178 if(len a > 7) 179 a = a[0:7]; 180 buf[0:] = a; 181 encrypt(key, buf, len buf); 182 return sys->sprint("%.2ux%.2ux%.2ux%.2ux", int buf[0], int buf[1], int buf[2], int buf[3]); 183} 184 185passtokey(p: string): array of byte 186{ 187 a := array of byte p; 188 n := len a; 189 if(n >= ANAMELEN) 190 n = ANAMELEN-1; 191 buf := array[ANAMELEN] of {* => byte ' '}; 192 buf[0:] = a[0:n]; 193 buf[n] = byte 0; 194 key := array[DESKEYLEN] of {* => byte 0}; 195 t := 0; 196 for(;;){ 197 for(i := 0; i < DESKEYLEN; i++) 198 key[i] = byte ((int buf[t+i] >> i) + (int buf[t+i+1] << (8 - (i+1)))); 199 if(n <= 8) 200 return key; 201 n -= 8; 202 t += 8; 203 if(n < 8){ 204 t -= 8 - n; 205 n = 8; 206 } 207 encrypt(key, buf[t:], 8); 208 } 209} 210 211parity := array[] of { 212 byte 16r01, byte 16r02, byte 16r04, byte 16r07, byte 16r08, byte 16r0b, byte 16r0d, byte 16r0e, 213 byte 16r10, byte 16r13, byte 16r15, byte 16r16, byte 16r19, byte 16r1a, byte 16r1c, byte 16r1f, 214 byte 16r20, byte 16r23, byte 16r25, byte 16r26, byte 16r29, byte 16r2a, byte 16r2c, byte 16r2f, 215 byte 16r31, byte 16r32, byte 16r34, byte 16r37, byte 16r38, byte 16r3b, byte 16r3d, byte 16r3e, 216 byte 16r40, byte 16r43, byte 16r45, byte 16r46, byte 16r49, byte 16r4a, byte 16r4c, byte 16r4f, 217 byte 16r51, byte 16r52, byte 16r54, byte 16r57, byte 16r58, byte 16r5b, byte 16r5d, byte 16r5e, 218 byte 16r61, byte 16r62, byte 16r64, byte 16r67, byte 16r68, byte 16r6b, byte 16r6d, byte 16r6e, 219 byte 16r70, byte 16r73, byte 16r75, byte 16r76, byte 16r79, byte 16r7a, byte 16r7c, byte 16r7f, 220 byte 16r80, byte 16r83, byte 16r85, byte 16r86, byte 16r89, byte 16r8a, byte 16r8c, byte 16r8f, 221 byte 16r91, byte 16r92, byte 16r94, byte 16r97, byte 16r98, byte 16r9b, byte 16r9d, byte 16r9e, 222 byte 16ra1, byte 16ra2, byte 16ra4, byte 16ra7, byte 16ra8, byte 16rab, byte 16rad, byte 16rae, 223 byte 16rb0, byte 16rb3, byte 16rb5, byte 16rb6, byte 16rb9, byte 16rba, byte 16rbc, byte 16rbf, 224 byte 16rc1, byte 16rc2, byte 16rc4, byte 16rc7, byte 16rc8, byte 16rcb, byte 16rcd, byte 16rce, 225 byte 16rd0, byte 16rd3, byte 16rd5, byte 16rd6, byte 16rd9, byte 16rda, byte 16rdc, byte 16rdf, 226 byte 16re0, byte 16re3, byte 16re5, byte 16re6, byte 16re9, byte 16rea, byte 16rec, byte 16ref, 227 byte 16rf1, byte 16rf2, byte 16rf4, byte 16rf7, byte 16rf8, byte 16rfb, byte 16rfd, byte 16rfe, 228}; 229 230des56to64(k56: array of byte): array of byte 231{ 232 k64 := array[8] of byte; 233 hi := (int k56[0]<<24)|(int k56[1]<<16)|(int k56[2]<<8)|int k56[3]; 234 lo := (int k56[4]<<24)|(int k56[5]<<16)|(int k56[6]<<8); 235 236 k64[0] = parity[(hi>>25)&16r7f]; 237 k64[1] = parity[(hi>>18)&16r7f]; 238 k64[2] = parity[(hi>>11)&16r7f]; 239 k64[3] = parity[(hi>>4)&16r7f]; 240 k64[4] = parity[((hi<<3)|int ((big lo & big 16rFFFFFFFF)>>29))&16r7f]; # watch the sign extension 241 k64[5] = parity[(lo>>22)&16r7f]; 242 k64[6] = parity[(lo>>15)&16r7f]; 243 k64[7] = parity[(lo>>8)&16r7f]; 244 return k64; 245} 246 247encrypt(key: array of byte, data: array of byte, n: int) 248{ 249 if(n < 8) 250 return; 251 crypt := load Crypt Crypt->PATH; 252 ds := crypt->dessetup(des56to64(key), nil); 253 n--; 254 r := n % 7; 255 n /= 7; 256 j := 0; 257 for(i := 0; i < n; i++){ 258 crypt->desecb(ds, data[j:], 8, Crypt->Encrypt); 259 j += 7; 260 } 261 if(r) 262 crypt->desecb(ds, data[j-7+r:], 8, Crypt->Encrypt); 263} 264 265decrypt(key: array of byte, data: array of byte, n: int) 266{ 267 if(n < 8) 268 return; 269 crypt := load Crypt Crypt->PATH; 270 ds := crypt->dessetup(des56to64(key), nil); 271 n--; 272 r := n % 7; 273 n /= 7; 274 j := n*7; 275 if(r) 276 crypt->desecb(ds, data[j-7+r:], 8, Crypt->Decrypt); 277 for(i := 0; i < n; i++){ 278 j -= 7; 279 crypt->desecb(ds, data[j:], 8, Crypt->Decrypt); 280 } 281} 282 283readn(fd: ref Sys->FD, nb: int): array of byte 284{ 285 buf:= array[nb] of byte; 286 if(sys->readn(fd, buf, nb) != nb) 287 return nil; 288 return buf; 289} 290 291pbmsg: con "AS protocol botch"; 292 293_asgetticket(fd: ref Sys->FD, tr: ref Ticketreq, key: array of byte): (ref Ticket, array of byte) 294{ 295 a := tr.pack(); 296 if(sys->write(fd, a, len a) < 0){ 297 sys->werrstr(pbmsg); 298 return (nil, nil); 299 } 300 a = _asrdresp(fd, 2*TICKETLEN); 301 if(a == nil) 302 return (nil, nil); 303 (nil, t) := Ticket.unpack(a, key); 304 return (t, a[TICKETLEN:]); # can't unpack both since the second uses server key 305} 306 307_asrdresp(fd: ref Sys->FD, n: int): array of byte 308{ 309 b := array[1] of byte; 310 if(sys->read(fd, b, 1) != 1){ 311 sys->werrstr(pbmsg); 312 return nil; 313 } 314 315 buf: array of byte; 316 case int b[0] { 317 AuthOK => 318 buf = readn(fd, n); 319 AuthOKvar => 320 b = readn(fd, 5); 321 if(b == nil) 322 break; 323 n = int string b; 324 if(n<= 0 || n > 4096) 325 break; 326 buf = readn(fd, n); 327 AuthErr => 328 b = readn(fd, 64); 329 if(b == nil) 330 break; 331 for(i:=0; i<len b && b[i] != byte 0; i++) 332 ; 333 sys->werrstr(sys->sprint("remote: %s", string b[0:i])); 334 return nil; 335 * => 336 sys->werrstr(sys->sprint("%s: resp %d", pbmsg, int b[0])); 337 return nil; 338 } 339 if(buf == nil) 340 sys->werrstr(pbmsg); 341 return buf; 342} 343