1implement Init; 2 3include "sys.m"; 4sys: Sys; 5FD, Connection, sprint, Dir: import sys; 6print, fprint, open, bind, mount, dial, sleep, read: import sys; 7 8include "draw.m"; 9draw: Draw; 10Context, Display, Font, Rect, Point, Image, Screen: import draw; 11 12include "prefab.m"; 13prefab: Prefab; 14Environ, Element, Compound, Style: import prefab; 15 16include "mpeg.m"; 17 18include "ir.m"; 19tirc: chan of int; # translated remote input (from irslave) 20irstopc: chan of int; # channel to irslave 21 22include "keyring.m"; 23kr: Keyring; 24IPint: import kr; 25 26Init: module 27{ 28 init: fn(); 29}; 30 31Shell: module 32{ 33 init: fn(ctxt: ref Context, argv: list of string); 34}; 35 36Signon: con "Dialing Local Service Provider\nWait a moment ..."; 37Login: con "Connected to Service Provider"; 38Intro: con "/mpeg/youwill2"; 39Garden: con "The Garden of Delights\nHieronymus Bosch"; 40 41rootfs(server: string): int 42{ 43 ok, n: int; 44 c: Connection; 45 err: string; 46 47 (ok, c) = dial("tcp!" + server + "!6666", nil); 48 if(ok < 0) 49 return -1; 50 51 if(kr != nil){ 52 ai := kr->readauthinfo("/nvfs/default"); 53 if(ai == nil){ 54 (ai, err) = register(server); 55 if(err != nil){ 56 status("registration failed: "+err+"\nPress a key on your remote\ncontrol to continue."); 57 # register() may have failed before Ir loaded. 58 if(tirc!=nil){ 59 <-tirc; 60 irstopc <-= 1; 61 } 62 } 63 statusbox = nil; 64 } 65 (id_or_err, secret) := kr->auth(c.dfd, ai, 0); 66 if(secret == nil){ 67 status("authentication failed: "+err); 68 sys->sleep(2000); 69 statusbox = nil; 70 (ai, err) = register(server); 71 if(err != nil){ 72 status("registration failed: "+err+"\nPress a key on your remote\ncontrol to continue."); 73 # register() may have failed before Ir loaded. 74 if(tirc!=nil){ 75 <-tirc; 76 irstopc <-= 1; 77 } 78 } 79 statusbox = nil; 80 } else { 81 # no line encryption 82 algbuf := array of byte "none"; 83 kr->sendmsg(c.dfd, algbuf, len algbuf); 84 } 85 } 86 87 c.cfd = nil; 88 n = mount(c.dfd, nil, "/", sys->MREPL, ""); 89 if(n > 0) 90 return 0; 91 return -1; 92} 93 94ones: ref Image; 95screen: ref Screen; 96menuenv, tvenv: ref Environ; 97Bootpreadlen: con 128; 98textfont: ref Font; 99disp: ref Display; 100env: ref Environ; 101statusbox: ref Compound; 102 103init() 104{ 105 shell: Shell; 106 nr, ntok: int; 107 c: ref Compound; 108 ls: list of string; 109 le, te, xe: ref Element; 110 spec: string; 111 112 sys = load Sys Sys->PATH; 113 draw = load Draw Draw->PATH; 114 prefab = load Prefab Prefab->PATH; 115 kr = load Keyring Keyring->PATH; 116 117 disp = Display.allocate(nil); 118 ones = disp.ones; 119 120 textfont = Font.open(disp, "*default*"); 121 screencolor := disp.rgb(161, 195, 209); 122 123 menustyle := ref Style( 124 textfont, # titlefont 125 textfont, # textfont 126 disp.color(16r55), # elemcolor 127 disp.color(draw->Black), # edgecolor 128 disp.color(draw->Yellow), # titlecolor 129 disp.color(draw->Black), # textcolor 130 disp.color(draw->White)); # highlightcolor 131 132 screen = Screen.allocate(disp.image, screencolor, 0); 133 screen.image.draw(screen.image.r, screencolor, ones, (0, 0)); 134 menuenv = ref Environ(screen, menustyle); 135 136 logo := disp.open("/lucent"); 137 phone := disp.open("/phone"); 138 if(phone == nil || logo == nil) { 139 print("open: /phone or /lucent: %r\n"); 140 exit; 141 } 142 143 # 144 # Setup what we need to call a server and 145 # Authenticate 146 # 147 bind("#l", "/net", sys->MREPL); 148 bind("#I", "/net", sys->MAFTER); 149 bind("#c", "/dev", sys->MAFTER); 150 bind("#H", "/dev", sys->MAFTER); 151 nvramfd := sys->open("#H/hd0nvram", sys->ORDWR); 152 if(nvramfd != nil){ 153 spec = sys->sprint("#Fhd0nvram", nvramfd.fd); 154 if(bind(spec, "/nvfs", sys->MAFTER|sys->MCREATE) < 0) 155 print("init: bind %s: %r\n", spec); 156 } 157 158 setsysname(); # set up system name 159 160 fd := open("/net/ipifc", sys->OWRITE); 161 if(fd == nil) { 162 print("init: open /net/ipifc: %r"); 163 exit; 164 } 165 fprint(fd, "bootp /net/ether0"); 166 167 fd = open("/net/bootp", sys->OREAD); 168 if(fd == nil) { 169 print("init: open /net/bootp: %r"); 170 exit; 171 } 172 173 buf := array[Bootpreadlen] of byte; 174 nr = read(fd, buf, len buf); 175 fd = nil; 176 if(nr <= 0) { 177 print("init: read /net/bootp: %r"); 178 exit; 179 } 180 181 (ntok, ls) = sys->tokenize(string buf, " \t\n"); 182 while(ls != nil) { 183 if(hd ls == "fsip"){ 184 ls = tl ls; 185 break; 186 } 187 ls = tl ls; 188 } 189 if(ls == nil) { 190 print("init: server address not in bootp read"); 191 exit; 192 } 193 194 zr := Rect((0,0), (0,0)); 195 196 le = Element.icon(menuenv, logo.r, logo, ones); 197 le = Element.elist(menuenv, le, Prefab->EVertical); 198 xe = Element.icon(menuenv, phone.r, phone, ones); 199 xe = Element.elist(menuenv, xe, Prefab->EHorizontal); 200 te = Element.text(menuenv, Signon, zr, Prefab->EText); 201 xe.append(te); 202 xe.adjust(Prefab->Adjpack, Prefab->Adjleft); 203 le.append(xe); 204 le.adjust(Prefab->Adjpack, Prefab->Adjup); 205 c = Compound.box(menuenv, (150, 100), 206 Element.text(menuenv, "Inferno", zr, Prefab->ETitle), le); 207 c.draw(); 208 209 while(rootfs(hd ls) < 0) 210 sleep(1000); 211 212 # 213 # default namespace 214 # 215 bind("#c", "/dev", sys->MBEFORE); # console 216 bind("#H", "/dev", sys->MAFTER); 217 if(spec != nil) 218 bind(spec, "/nvfs", sys->MBEFORE|sys->MCREATE); # our keys 219 bind("#E", "/dev", sys->MBEFORE); # mpeg 220 bind("#l", "/net", sys->MBEFORE); # ethernet 221 bind("#I", "/net", sys->MBEFORE); # TCP/IP 222 bind("#V", "/dev", sys->MAFTER); # hauppauge TV 223 bind("#p", "/prog", sys->MREPL); # prog device 224 sys->bind("#d", "/fd", Sys->MREPL); 225 226 setclock(); 227 228 le = Element.icon(menuenv, logo.r, logo, ones); 229 le = Element.elist(menuenv, le, Prefab->EVertical); 230 xe = Element.text(menuenv, Login, zr, Prefab->EText); 231 le.append(xe); 232 233 i := disp.newimage(Rect((0, 0), (320, 240)), 3, 0, 0); 234 i.draw(i.r, menustyle.elemcolor, ones, i.r.min); 235 xe = Element.icon(menuenv, i.r, i, ones); 236 le.append(xe); 237 238 le.adjust(Prefab->Adjpack, Prefab->Adjup); 239 c = Compound.box(menuenv, (160, 50), 240 Element.text(menuenv, "Inferno", zr, Prefab->ETitle), le); 241 c.draw(); 242 243 xc: chan of string; 244 mpeg := load Mpeg Mpeg->PATH; 245 if(mpeg != nil) { 246 xc = chan of string; 247 r := (hd tl tl c.contents.kids).r; 248 s := mpeg->play(disp, c.image, 1, r, Intro, xc); 249 if(s != "") { 250 print("mpeg: %s\n", s); 251 xc = nil; 252 } 253 } 254 255 i2 := disp.open("/icons/delight.bit"); 256 i.draw(i.r, i2, ones, i2.r.min); 257 i2 = nil; 258 if(xc != nil) 259 <-xc; 260 261 le.append(Element.text(menuenv, Garden, le.r, Prefab->EText)); 262 le.adjust(Prefab->Adjpack, Prefab->Adjup); 263 c = Compound.box(menuenv, (160, 50), 264 Element.text(menuenv, "Inferno", zr, Prefab->ETitle), le); 265 c.draw(); 266 267 sleep(5000); 268 269 # Do a bind to force applications to use IR module built 270 # into the kernel. 271 if(bind("#/./ir", Ir->PATH, sys->MREPL) < 0) 272 print("init: bind ir: %r\n"); 273 # Uncomment the next line to load sh.dis. 274# shell = load Shell "/dis/sh.dis"; 275 dc : ref Context; 276 # Comment the next 2 lines to load sh.dis. 277 shell = load Shell "/dis/mux/mux.dis"; 278 dc = ref Context(screen, disp, nil, nil, nil, nil, nil); 279 if(shell == nil) { 280 print("init: load /dis/sh.dis: %r"); 281 exit; 282 } 283 shell->init(dc, nil); 284} 285 286setclock() 287{ 288 (ok, dir) := sys->stat("/"); 289 if (ok < 0) { 290 print("init: stat /: %r"); 291 return; 292 } 293 294 fd := sys->open("/dev/time", sys->OWRITE); 295 if (fd == nil) { 296 print("init: open /dev/time: %r"); 297 return; 298 } 299 300 # Time is kept as microsecs, atime is in secs 301 b := array of byte sprint("%d000000", dir.atime); 302 if (sys->write(fd, b, len b) != len b) 303 print("init: write /dev/time: %r"); 304} 305 306register(signer: string): (ref Keyring->Authinfo, string) 307{ 308 309 # get box id 310 fd := sys->open("/nvfs/ID", sys->OREAD); 311 if(fd == nil){ 312 fd = sys->create("/nvfs/ID", sys->OWRITE, 8r664); 313 if(fd == nil) 314 return (nil, "can't create /nvfs/ID"); 315 if(sys->fprint(fd, "LT%d", randomint()) < 0) 316 return (nil, "can't write /nvfs/ID"); 317 fd = sys->open("/nvfs/ID", sys->OREAD); 318 } 319 if(fd == nil) 320 return (nil, "can't open /nvfs/ID"); 321 322 buf := array[64] of byte; 323 n := sys->read(fd, buf, (len buf) - 1); 324 if(n <= 0) 325 return (nil, "can't read /nvfs/ID"); 326 327 boxid := string buf[0:n]; 328 fd = nil; 329 buf = nil; 330 331 # Set-up for user input via remote control. 332 tirc = chan of int; 333 irstopc = chan of int; 334 spawn irslave(tirc, irstopc); 335 case dialogue("Register with your service provider?", "yes\nno") { 336 0 => 337 ; 338 * => 339 return (nil, "registration not desired"); 340 } 341 342 # a holder 343 info := ref Keyring->Authinfo; 344 345 # contact signer 346# status("looking for signer"); 347# signer := virgil->virgil("$SIGNER"); 348# if(signer == nil) 349# return (nil, "can't find signer"); 350 status("dialing tcp!"+signer+"!6671"); 351 (ok, c) := sys->dial("tcp!"+signer+"!6671", nil); 352 if(!ok) 353 return (nil, "can't contact signer"); 354 355 # get signer's public key and diffie helman parameters 356 status("getting signer's key"); 357 spkbuf := kr->getmsg(c.dfd); 358 if(spkbuf == nil) 359 return (nil, "can't read signer's key"); 360 info.spk = kr->strtopk(string spkbuf); 361 if(info.spk == nil) 362 return (nil, "bad key from signer"); 363 alphabuf := kr->getmsg(c.dfd); 364 if(alphabuf == nil) 365 return (nil, "can't read dh alpha"); 366 info.alpha = IPint.b64toip(string alphabuf); 367 pbuf := kr->getmsg(c.dfd); 368 if(pbuf == nil) 369 return (nil, "can't read dh mod"); 370 info.p = IPint.b64toip(string pbuf); 371 372 # generate our key from system parameters 373 status("generating our key"); 374 info.mysk = kr->genSKfromPK(info.spk, boxid); 375 if(info.mysk == nil) 376 return (nil, "can't generate our own key"); 377 info.mypk = kr->sktopk(info.mysk); 378 379 # send signer our public key 380 mypkbuf := array of byte kr->pktostr(info.mypk); 381 kr->sendmsg(c.dfd, mypkbuf, len mypkbuf); 382 383 # get blind certificate 384 status("getting blinded certificate"); 385 certbuf := kr->getmsg(c.dfd); 386 if(certbuf == nil) 387 return (nil, "can't read signed key"); 388 389 # verify we've got the right stuff 390 if(!verify(boxid, spkbuf, mypkbuf, certbuf)) 391 return (nil, "verification failed, try again"); 392 393 # contact counter signer 394 status("dialing tcp!"+signer+"!6672"); 395 (ok, c) = sys->dial("tcp!"+signer+"!6672", nil); 396 if(!ok) 397 return (nil, "can't contact countersigner"); 398 399 # send boxid 400 buf = array of byte boxid; 401 kr->sendmsg(c.dfd, buf, len buf); 402 403 # get blinding mask 404 status("unblinding certificate"); 405 mask := kr->getmsg(c.dfd); 406 if(len mask != len certbuf) 407 return (nil, "bad mask length"); 408 for(i := 0; i < len mask; i++) 409 certbuf[i] = certbuf[i] ^ mask[i]; 410 info.cert = kr->strtocert(string certbuf); 411 412 status("verifying certificate"); 413 state := kr->sha(mypkbuf, len mypkbuf, nil, nil); 414 if(kr->verify(info.spk, info.cert, state) == 0) 415 return (nil, "bad certificate"); 416 417 status("storing keys"); 418 kr->writeauthinfo("/nvfs/default", info); 419 420 status("Congratulations, you are registered.\nPress a key to continue."); 421 <-tirc; 422 irstopc <-= 1; 423 424 return (info, nil); 425} 426 427dialogue(expl: string, selection: string): int 428{ 429 c := Compound.textbox(menuenv, ((100, 100), (100, 100)), expl, selection); 430 c.draw(); 431 for(;;){ 432 (key, index, nil) := c.select(c.contents, 0, tirc); 433 case key { 434 Ir->Select => 435 return index; 436 Ir->Enter => 437 return -1; 438 } 439 } 440} 441 442status(expl: string) 443{ 444# title := Element.text(menuenv, "registration\nstatus", ((0,0),(0,0)), Prefab->ETitle); 445# msg := Element.text(menuenv, expl, ((0,0),(0,0)), Prefab->EText); 446# c := Compound.box(menuenv, (100, 100), title, msg); 447 448 c := Compound.textbox(menuenv, ((100, 100),(100,100)), "Registration status", expl); 449 c.draw(); 450 statusbox = c; 451} 452 453pro:= array[] of { 454 "alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", 455 "hotel", "india", "juliet", "kilo", "lima", "mike", "nancy", "oscar", 456 "poppa", "quebec", "romeo", "sierra", "tango", "uniform", 457 "victor", "whiskey", "xray", "yankee", "zulu" 458}; 459 460# 461# prompt for acceptance 462# 463verify(boxid: string, hispk, mypk, cert: array of byte): int 464{ 465 s: string; 466 467 # hash the string 468 state := kr->md5(hispk, len hispk, nil, nil); 469 kr->md5(mypk, len mypk, nil, state); 470 digest := array[Keyring->MD5dlen] of byte; 471 kr->md5(cert, len cert, digest, state); 472 473 title := Element.elist(menuenv, nil, Prefab->EVertical); 474 subtitle := Element.text(menuenv, "Telephone your service provider\n to register. You will need\nthe following:\n", ((0,0),(0,0)), Prefab->ETitle); 475 title.append(subtitle); 476 477 line := Element.text(menuenv, "boxid is '"+boxid+"'.", ((0,0),(0,0)), Prefab->ETitle); 478 title.append(line); 479 for(i := 0; i < len digest; i++){ 480 line = Element.elist(menuenv, nil, Prefab->EHorizontal); 481 s = (string (2*i)) + ": " + pro[((int digest[i])>>4)%len pro]; 482 line.append(Element.text(menuenv, s, ((0,0),(0,0)), Prefab->ETitle)); 483 484 s = (string (2*i+1)) + ": " + pro[(int digest[i])%len pro] + "\n"; 485 line.append(Element.text(menuenv, s, ((0,0),(200,0)), Prefab->ETitle)); 486 487 line.adjust(Prefab->Adjequal, Prefab->Adjleft); 488 title.append(line); 489 } 490 title.adjust(Prefab->Adjpack, Prefab->Adjleft); 491 492 le := Element.elist(menuenv, nil, Prefab->EHorizontal); 493 le.append(Element.text(menuenv, " accept ", ((0, 0), (0, 0)), Prefab->EText)); 494 le.append(Element.text(menuenv, " reject ", ((0, 0), (0, 0)), Prefab->EText)); 495 le.adjust(Prefab->Adjpack, Prefab->Adjleft); 496 497 c := Compound.box(menuenv, (50, 50), title, le); 498 c.draw(); 499 500 for(;;){ 501 (key, index, nil) := c.select(c.contents, 0, tirc); 502 case key { 503 Ir->Select => 504 if(index == 0) 505 return 1; 506 return 0; 507 Ir->Enter => 508 return 0; 509 } 510 } 511 512 return 0; 513} 514 515randomint(): int 516{ 517 fd := sys->open("/dev/random", sys->OREAD); 518 if(fd == nil) 519 return 0; 520 buf := array[4] of byte; 521 sys->read(fd, buf, 4); 522 rand := 0; 523 for(i := 0; i < 4; i++) 524 rand = (rand<<8) | int buf[i]; 525 return rand; 526} 527 528# Reads real (if possible) or simulated remote, returns Ir events on irc. 529# Must be a separate thread to be able to 1) read raw Ir input channel 530# and 2) write translated Ir input data on output channel. 531irslave(irc, stopc: chan of int) 532{ 533 in, irpid: int; 534 buf: list of int; 535 outc: chan of int; 536 537 irchan := chan of int; # Untranslated Ir input channel. 538 irpidch := chan of int; # Ir reader pid channel. 539 irmod := load Ir "#/./ir"; # Module built into kernel. 540 541 if(irmod==nil){ 542 print("irslave: failed to load #/./ir"); 543 return; 544 } 545 if(irmod->init(irchan, irpidch)<0){ 546 print("irslave: failed to initialize ir"); 547 return; 548 } 549 irpid =<-irpidch; 550 551 hdbuf := 0; 552 dummy := chan of int; 553 for(;;){ 554 if(buf == nil){ 555 outc = dummy; 556 }else{ 557 outc = irc; 558 hdbuf = hd buf; 559 } 560 alt{ 561 in = <-irchan => 562 buf = append(buf, in); 563 outc <-= irmod->translate(hdbuf) => 564 buf = tl buf; 565 <-stopc =>{ 566 killir(irpid); 567 return; 568 } 569 } 570 } 571} 572 573append(l: list of int, i: int): list of int 574{ 575 if(l == nil) 576 return i :: nil; 577 return hd l :: append(tl l, i); 578} 579 580killir(irpid: int) 581{ 582 pid := sys->sprint("%d", irpid); 583 fd := sys->open("#p/"+pid+"/ctl", sys->OWRITE); 584 if(fd==nil) { 585 print("init: process %s: %r\n", pid); 586 return; 587 } 588 589 msg := array of byte "kill"; 590 n := sys->write(fd, msg, len msg); 591 if(n < 0) { 592 print("init: message for %s: %r\n", pid); 593 return; 594 } 595} 596 597# 598# Set system name from nvram 599# 600setsysname() 601{ 602 fd := open("/nvfs/ID", sys->OREAD); 603 if(fd == nil) 604 return; 605 fds := open("/dev/sysname", sys->OWRITE); 606 if(fds == nil) 607 return; 608 buf := array[128] of byte; 609 nr := sys->read(fd, buf, len buf); 610 if(nr <= 0) 611 return; 612 sys->write(fds, buf, nr); 613} 614