]> asedeno.scripts.mit.edu Git - pssh.git/blob - main.c
updates to device ids
[pssh.git] / main.c
1 /**********
2  * Copyright (c) 2003-2005 Greg Parker.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY GREG PARKER ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  **********/
24
25 #include "includes.h"
26 #include "ssh/ssh.h"
27 #include "vt100/vt100.h"
28 #include "rsrc/rsrc.h"
29 #include "crypto/rand.h"
30 #include "armstubs.h"
31
32 #include "data/connectionlist.h"
33 #include "data/hostkeys.h"
34 #include "data/memolist.h"
35 #include "data/prefs.h"
36 #include "data/publickeys.h"
37
38 #include "forms/about.h"
39 #include "forms/connectionprefsform.h"
40 #include "forms/detailsform.h"
41 #include "forms/displayprefsform.h"
42 #include "forms/hostkeysform.h"
43 #include "forms/hostkeydetailsform.h"
44 #include "forms/kbdintform.h"
45 #include "forms/kbdint0form.h"
46 #include "forms/keyboardprefsform.h"
47 #include "forms/loginform.h"
48 #include "forms/mainform.h"
49 #include "forms/memoform.h"
50 #include "forms/passwordform.h"
51 #include "forms/passphraseform.h"
52 #include "forms/publickeysform.h"
53 #include "forms/publickeychoiceform.h"
54 #include "forms/publickeydetailsform.h"
55 #include "forms/terminalform.h"
56 #include "forms/DIA.h"
57
58 #include "crypto/openssl/bn/bn.h"
59 #include "crypto/openssl/md5/md5.h"
60
61 Err errno;
62
63
64
65 UInt16 NetLibCount = 0;
66 struct ssh_session_t *ss = NULL;
67
68
69 // fixme move to recordlist
70 DmOpenRef OpenDB(UInt32 type, char *name, Boolean resDB, Boolean create)
71 {
72     DmOpenRef result;
73     Err err;
74
75     result = DmOpenDatabaseByTypeCreator(type, PSSH_CREATOR, dmModeReadWrite);
76     if (!result  &&  create) {
77         UInt16 card;
78         LocalID id;
79         UInt16 attr;
80
81         err = DmCreateDatabase(0, name, PSSH_CREATOR, type, resDB);
82         if (err) { complain_int("db 1", err); return 0; }
83         result = DmOpenDatabaseByTypeCreator(type, PSSH_CREATOR, dmModeReadWrite);
84         if (!result) { complain_int("db 2", DmGetLastErr()); return 0; }
85
86         // Set backup bit
87         DmOpenDatabaseInfo(result, &id, NULL, NULL, &card, NULL);
88         DmDatabaseInfo(card, id, NULL, &attr, NULL, NULL, NULL, 
89                        NULL, NULL, NULL, NULL, NULL, NULL);
90         attr |= dmHdrAttrBackup;
91         DmSetDatabaseInfo(card, id, NULL, &attr, NULL, NULL, NULL, 
92                           NULL, NULL, NULL, NULL, NULL, NULL);
93     }
94
95     return result;
96 }
97
98
99
100
101
102 void complain(char *err)
103 {
104     char errnobuf[20];
105     WinPushDrawState();
106     WinSetCoordinateSystem(kCoordinatesStandard);
107     FrmCustomAlert(AlertFormID, err, StrIToA(errnobuf, errno), " ");
108     WinPopDrawState();
109 }
110
111 void complain_int(char *err, uint32_t i) 
112 {
113     char intbuf[20];
114     WinPushDrawState();
115     WinSetCoordinateSystem(kCoordinatesStandard);
116     FrmCustomAlert(AlertFormID, err, StrIToA(intbuf, i), " ");
117     WinPopDrawState();
118 }
119
120
121 Boolean ApplicationHandleEvent(EventPtr e)
122 {
123     if (e->eType == frmLoadEvent) {
124         UInt16 formId = e->data.frmLoad.formID;
125         FormPtr frmP = FrmInitForm(formId);
126         FrmSetActiveForm(frmP);
127
128         switch(formId) {
129         case MainFormID:
130             SetResizePolicy(formId);
131             SetResizeCallback(formId, MainFormResize);
132             FrmSetEventHandler(frmP, MainFormHandleEvent);
133             break;
134         case DetailsFormID:
135             SetResizePolicy(formId);
136             FrmSetEventHandler(frmP, DetailsFormHandleEvent);
137             break;
138         case LoginFormID:
139             SetResizePolicy(formId);
140             FrmSetEventHandler(frmP, LoginFormHandleEvent);
141             break;
142         case PasswordFormID:
143             SetResizePolicy(formId);
144             FrmSetEventHandler(frmP, PasswordFormHandleEvent);
145             break;
146         case TerminalFormID:
147             SetResizePolicy(formId);
148             SetResizeCallback(formId, TerminalFormResize);
149             FrmSetEventHandler(frmP, TerminalFormHandleEvent);
150             break;
151         case HostKeysFormID:
152             SetResizePolicy(formId);
153             SetResizeCallback(formId, HostKeysFormResize);
154             FrmSetEventHandler(frmP, HostKeysFormHandleEvent);
155             break;
156         case HostKeyDetailsFormID:
157             SetResizePolicy(formId);
158             FrmSetEventHandler(frmP, HostKeyDetailsFormHandleEvent);
159             break;
160         case AboutFormID:
161             SetResizePolicy(formId);
162             FrmSetEventHandler(frmP, AboutFormHandleEvent);
163             break;
164         case CreditsFormID:
165             SetResizePolicy(formId);
166             FrmSetEventHandler(frmP, CreditsFormHandleEvent);
167             break;
168         case DisplayPrefsFormID:
169             SetResizePolicy(formId);
170             FrmSetEventHandler(frmP, DisplayPrefsFormHandleEvent);
171             break;
172         case ConnectionPrefsFormID:
173             SetResizePolicy(formId);
174             FrmSetEventHandler(frmP, ConnectionPrefsFormHandleEvent);
175             break;
176         case KeyboardPrefsFormID:
177             SetResizePolicy(formId);
178             FrmSetEventHandler(frmP, KeyboardPrefsFormHandleEvent);
179             break;
180         case MemoFormID:
181             SetResizePolicy(formId);
182             SetResizeCallback(formId, MemoFormResize);
183             FrmSetEventHandler(frmP, MemoFormHandleEvent);
184             break;
185         case PublicKeysFormID:
186             SetResizePolicy(formId);
187             SetResizeCallback(formId, PublicKeysFormResize);
188             FrmSetEventHandler(frmP, PublicKeysFormHandleEvent);
189             break;
190         case PublicKeyDetailsFormID:
191             SetResizePolicy(formId);
192             FrmSetEventHandler(frmP, PublicKeyDetailsFormHandleEvent);
193             break;
194         case PassphraseFormID:
195             SetResizePolicy(formId);
196             FrmSetEventHandler(frmP, PasswordFormHandleEvent);
197             break;
198         case PublicKeyChoiceFormID:
199             SetResizePolicy(formId);
200             FrmSetEventHandler(frmP, PublicKeyChoiceFormHandleEvent);
201             break;
202         case KbdIntFormID:
203             SetResizePolicy(formId);
204             FrmSetEventHandler(frmP, KbdIntFormHandleEvent);
205             break;
206         case KbdInt0FormID:
207             SetResizePolicy(formId);
208             FrmSetEventHandler(frmP, KbdInt0FormHandleEvent);
209             break;
210         case BannerFormID:
211             SetResizePolicy(formId);
212             FrmSetEventHandler(frmP, BannerFormHandleEvent);
213             break;
214         default:
215             break;
216         }
217         return true;
218     }
219
220     return false;
221 }
222
223
224 static Boolean RomVersionCompatible (UInt32 requiredVersion)
225 {
226     UInt32 romVersion;
227     
228     // See if we're on in minimum required version of the ROM or later.
229     // The system records the version number in a feature.  A feature is a
230     // piece of information which can be looked up by a creator and feature
231     // number.
232     FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
233     return (romVersion >= requiredVersion);
234 }
235
236
237 static Boolean CPUIsARM(void)
238 {
239     UInt32 cpu;
240     FtrGet(sysFtrCreator, sysFtrNumProcessorID, &cpu);
241     return sysFtrNumProcessorIsARM(cpu);
242 }
243
244 static void StartupError(char *msg, UInt16 launchFlags)
245 {
246     UInt32 romVersion;
247     FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
248
249     // If the user launched the app from the launcher, explain
250     // why the app shouldn't run.  If the app was contacted for something
251     // else, like it was asked to find a string by the system find, then
252     // don't bother the user with a warning dialog.  These flags tell how
253     // the app was launched to decided if a warning should be displayed.
254     if ((launchFlags & (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) ==
255         (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp))
256     {
257         complain(msg);
258         
259         // Pilot 1.0 will continuously relaunch this app unless we switch to 
260         // another safe one.  The sysFileCDefaultApp is considered "safe".
261         if (romVersion < 0x02000000)
262         {
263             AppLaunchWithCommand(sysFileCDefaultApp, 
264                                  sysAppLaunchCmdNormalLaunch, NULL);
265         }
266     }
267 }
268
269
270 static Boolean NetLibAvailable(void) 
271 {
272     Err err;
273     UInt32 version;
274     
275     err = FtrGet(netFtrCreator, netFtrNumVersion, &version);
276     if (err) return false;
277     // any NetLib version is OK
278
279     err = SysLibFind("Net.lib", &AppNetRefnum);
280     if (err) return false;
281     
282     return true;
283 }
284
285
286 UInt32 PilotMain(UInt16 cmd, void *cmdPBP, UInt16 launchFlags)
287 {
288     int loopcount = 0;
289     UInt16 version;
290     int i;
291     UInt32 tenth = SysTicksPerSecond() / 10;
292     UInt32 lastUpdate = 0;
293     UInt32 now;
294
295     if (cmd == sysAppLaunchCmdNotify) {
296         HandleResizeNotification(((SysNotifyParamType *)cmdPBP)->notifyType);
297     }
298
299     // we don't handle search et al.
300     if (cmd != sysAppLaunchCmdNormalLaunch) return 0;
301
302     // ARM CPU required
303     // fixme unless better bnlib is written
304     if (!CPUIsARM()) {
305         StartupError("pssh requires an ARM processor", launchFlags);
306         return 0;
307     }
308
309     // ROM version 3.5+ required
310     // fixme this should always pass given ARM
311     if (!RomVersionCompatible(sysMakeROMVersion(3,5,0,0,0))) {
312         StartupError("pssh requires ROM version 3.5 or later", launchFlags);
313         return 0;
314     }
315
316     // NetLib required (any version)
317     if (!NetLibAvailable()) {
318         StartupError("pssh requires NetLib", launchFlags);
319         return 0;
320     }
321
322     if (!init_arm()) {
323         StartupError("Couldn't load ARM code", launchFlags);
324         return 0;
325     }
326
327     if (!ConnectionListInit()) {
328         StartupError("Couldn't open connection list", launchFlags);
329         return 0;
330     }
331
332     if (!HostKeysInit()) {
333         StartupError("Couldn't open known host key list", launchFlags);
334         return 0;
335     }
336
337     if (!PublicKeysInit()) {
338         StartupError("Couldn't open public key list", launchFlags);
339         return 0;
340     }
341
342     if (!PrefsInit()) {
343         StartupError("Couldn't open preferences", launchFlags);
344         return 0;
345     }
346
347     {
348         uint32_t warned;
349         Err err;
350         
351         err = FtrGet(PSSH_CREATOR, ftrSecurityWarning, &warned);
352         if (err) warned = 0;
353         if (!warned) {
354             FrmCustomAlert(AlertFormID, "WARNING: pssh is substantially UNTESTED and probably INSECURE. Do not use for security-critical applications.", " ", " ");
355             warned = 1;
356             FtrSet(PSSH_CREATOR, ftrSecurityWarning, warned);
357         }
358     }
359
360     // init virtual Graffiti area API, if any
361     InitializeResizeSupport(ResizeDataID);
362     LoadResizePrefs(PSSH_CREATOR, ResizeDataID);
363
364     RAND_init();
365
366     /*
367     {
368         // fixme quickie dynamic heap check
369         UInt16 heapID;
370         UInt32 free;
371         UInt32 max;
372         UInt32 size;
373         heapID = MemHeapID(0, 0);
374         MemHeapFreeBytes(heapID, &free, &max);
375         size = MemHeapSize(heapID);
376         complain_int("dynamic heap size ", size);
377         complain_int("dynamic heap free ", free);
378         complain_int("dynamic heap max chunk ", max);
379     }
380     */
381
382     {
383         MemHandle fontH;
384         FontType *fontP;
385
386 #define DEFINEFONT(f) \
387         fontH = DmGetResource(fontExtRscType, f); \
388         fontP = MemHandleLock(fontH); \
389         FntDefineFont((FontID)f, fontP);
390
391         DEFINEFONT(NanoFontSingleID);
392         DEFINEFONT(NanoFontDoubleID);
393         DEFINEFONT(MediumFontSingleID);
394         DEFINEFONT(MediumFontDoubleID);
395         DEFINEFONT(PasswordFontID);
396
397 #undef DEFINEFONT
398     }
399
400     // 10 second timeout for DNS and connect()
401     AppNetTimeout = SysTicksPerSecond() * 10;
402
403     FrmGotoForm(MainFormID);
404
405     do {
406         Int32 delay;
407         int lastEventType;
408
409         if (ss  &&  !ssh_is_closed(ss)) {
410             fd_set rfds;
411             int maxfd;
412             int ssfd;
413             int selected;
414             struct timeval tv;
415
416             FD_ZERO(&rfds);
417             FD_SET(STDIN_FILENO, &rfds);
418             
419             ssfd = ssh_request_select(ss, &rfds, NULL);
420             maxfd = MAX(STDIN_FILENO, ssfd);
421
422             // Don't block in select() if there are events in the event queue.
423             // fixme even if there are no events, keep block time short 
424             // because of stuck-in-select problem
425             if (EvtEventAvail()) {
426                 tv.tv_usec = 0;
427                 tv.tv_sec = 0;
428             } else {
429                 tv.tv_usec = 100000L;  // 1/10 sec
430                 tv.tv_sec = 0;
431             }
432
433             selected = select(maxfd + 1, &rfds, NULL, NULL, &tv);
434
435             if (selected >= 0) {
436                 if (FD_ISSET(ssfd, &rfds)) {
437                     EventType e = {0};
438                     e.eType = usrNetEvent;
439                     EvtAddUniqueEventToQueue(&e, 0, true);
440                 }
441             }
442
443             delay = 0; // DON'T block in EvtGetEvent
444         } else {
445             // No sockets to select() yet
446             delay = -1;  // DO block in EvtGetEvent (forever)
447         }
448
449
450         {
451             EventType event;
452             Err err;
453
454             EvtGetEvent(&event, delay);
455
456             if (event.eType == usrNetEvent) {
457                 // Handle incoming network data
458                 if (ss  &&  !ssh_is_closed(ss)) {
459                     ssh_read(ss);
460                 }
461             }
462
463             if (TerminalFormStealEvent(&event)) {
464                 FrmDispatchEvent(&event);
465             } else {
466                 if (!SysHandleEvent(&event)) {
467                     if (!MenuHandleEvent(NULL, &event, &err)) {
468                         if (!ApplicationHandleEvent(&event)) {
469                             FrmDispatchEvent(&event);
470                         }
471                     }
472                 }
473             }
474
475             if (ss) {
476                 now = TimGetTicks();
477                 if (now >= lastUpdate + tenth) {
478                     ssh_task(ss);
479                     lastUpdate = now;
480                 }
481             }
482
483             if (event.eType == keyDownEvent || event.eType == keyUpEvent || 
484                 event.eType == penUpEvent   || event.eType == penMoveEvent) 
485             {
486                 RAND_add_event_entropy(&event);
487             }
488
489             if (event.eType == appStopEvent) break;
490         }
491     } while (1);
492
493  done:
494     FrmSaveAllForms();
495     FrmCloseAllForms();
496
497     MemoListFree();
498     PublicKeysFree();
499     HostKeysFree();
500     ConnectionListFree();
501
502     for (i = 0; i < NetLibCount; i++) {
503         NetLibClose(AppNetRefnum, false);
504     }
505
506     SaveResizePrefs(PSSH_CREATOR, ResizeDataID, 0);
507     TerminateResizeSupport();
508
509     RAND_stop();
510
511     PealUnload(arm_module);
512
513     return 0;
514 }
515
516
517
518 /*
519
520 #if 0
521         // memory leak tracing
522         {
523             static int inited = 0;
524             static UInt16 heapID;
525             static uint32_t gen = 0;
526             UInt32 free;
527             UInt32 max;
528             UInt32 size;
529             extern uint32_t ev_block_count;
530             extern uint32_t ev_byte_count;
531             //            extern uint32_t ev_blocks_used;
532             if (!inited) {
533                 inited = 1;
534                 heapID = MemHeapID(0, 0);
535             }
536             MemHeapFreeBytes(heapID, &free, &max);
537             size = MemHeapSize(heapID);
538             
539             debug_printf("mem %luK,%lu[%luK]AB,%lu gen", (size-free)/1024, ev_block_count, ev_byte_count/1024, gen++);
540             // if (gen % 100 == 0) arena_dump_blocks();
541         }
542 #endif
543         
544         // fixme write queue
545         //if (ssh_is_selected(ss, &wfds)) {
546         // ssh_write(ss);
547         // }
548         */