/* cnct.c */ #define CNCTMASTER /* * Includes */ #include #include #include "vcnct.h" #include "dfault.h" #include "evtdef.h" #include "hstdef.h" #include "prodef.h" #include "kbkeys.h" #include "tsxutl.h" #include "rtfile.h" #include "kbdutl.h" #include "cliutl.h" #include "usrblk.h" #include "inicli.h" #include "suspnd.h" /* * Internal routines */ extern int dosess(); /* process loop */ extern int inprocess(); /* (sknum) process incoming data */ extern int newkey(); /* (tw) filter for command sequences */ extern int dokey(); /* (tw,c) process keyboard keys */ extern VOID lsterr(); /* list error routine for TSXUTL.C */ extern int question(); /* (cstr,clen,qstr) question routine */ extern int rtresp(); /* (st,ln) get response */ extern int keygets(); /* (str,lim,echo) get line from keyboard */ extern int getword(); /* (string,word) extract a word */ extern char *stptok(); /* (p,to,len,dlm) stop on token */ extern char *stpblk(); /* (ch) stop on blank */ extern VOID strlwr(); /* (st) convert string to lower case */ extern int chkusr(); /* check username / password */ extern int Scompass(); /* (ps,en) compare passwords */ extern VOID printtxt(); /* (txt) printout text */ /* * debug - * * bit 0 (0x01) enable printing of internal events */ #define DBUGTRUE -1 /* all debuggers */ static char *usetxt[] = { "", #ifdef DEBUGOPTION " CNCT destination [?] [-hp] [-d level]", " ? List the Help Text and Exit CNCT", " d level Debug Level", " 1 - enable event printing", #else " CNCT destination [?] [-hp]", " ? List the Help Text and Exit CNCT", #endif " h List the Help Text and Open Connection", " p filename Specify the Password Filespec", "", 0 }; static char *hlptxt[] = { "", "Keyboard usage for CNCT-11", "-------- ----- --- -------", "", "The metacharacter 'M->' is ^A", "M->C open capture file M->O abort output", "M->D close capture file M->Q are you there?", "M->F FTP [internet address] M->S skip to end of buffer", "M->H this help screen M->X close connection", "M->I type my internet address M->Y interrupt process", "", " ^? abort CNCT session", "", 0 }; char xs[2]; /* dumby array for TSXUTL.C */ char *pass = "sy:paswrd.fil"; /* password file */ int pswdreqd = 1; /* password required */ int viewmode = 1; int cnctopen = 0; /* connection open flag */ int cnctskt = -1; /* socket number */ struct socket *skt = -1; /* socket */ struct twin *tw = NULL; /* session */ char parsedat[80]; /* parsing data */ #define ABORT (-3) main(argc,argv) int argc; char *argv[]; { int c,i,j,k; int ev; /* * Initialize for TSX+ clients */ inicli(); /* * Initialize kb handler * Set the break character to ^C */ kb_init(0x03); /* * identify self */ printtxt(vrstxt); /* * parse arguments */ parsedat[0] = '\0'; for(i=1; isession); do { ev = dosess(); if(ev==0) suspnd(0); } while (ev != -1); suspnd(0); errhandle(); kb_puts("\r\nEscaping from CNCT\r\n"); exit(0); } /* * dosess * * dosess is an infinite loop serving two sources * of external input in order of precedence: * - keyboard strokes * - message events */ int dosess() { int c,cl,ev,dat; char st[100]; /* * do all key translations */ switch(viewmode) { default: /* * This gives precedence to the * keyboard over the network. */ while(0<=(c=newkey())) { if(c==A_BRK) return(-1); } break; case 1: if(fndbrk) return(-1); c = kb_char(); if(c == A_X) { return(-1); } else if(c != -1) { kb_puts("\r\nOther commands require an open session."); kb_puts("\r\n^A X - Escape from CNCT\r\n"); } break; } /* * Check for any relevant messages * that need to be handled by me */ ev = Sgetevent(SCKTCLASS | CONCLASS | USERCLASS | ERRCLASS | MSGCLASS | ABORTCLASS, &cl, &dat); if(ev!=0 && dat==cnctskt) { switch(cl) { case CONCLASS: switch(ev) { case CONOPEN: /* a connection has just opened */ /* * Log the Session */ sprintf(st,"CNCT: %s", parsedat); logsession(cnctskt,st); cnctopen = 1; viewmode = 0; break; case CONCLOSE: /* connection is closing */ if(0capon) { rtclose(tw->capfp); /* close the capture file */ tw->capon = 0; } kb_puts("\r\nConnection closed.\r\n"); return(A_BRK); } if(cnt) { skdeque(cnctskt); /* dequeue the data */ /* * send the string where it belongs * 1. Check for a capture file. * 2. send to screen */ if(tw->capon) fwrite(s,cnt,1,tw->capfp); s[cnt] = '\0'; kb_puts(s); return(1); } return(0); } /* newkey * * filter for command key sequences */ int newkey() { register int c; if(fndbrk) { fndbrk = 0; c = A_BRK; } else { c = kb_char(); } if(c>0) c = dokey(c); if(pushsk) skenque(cnctskt,1); return(c); } /* * dokey * * Translates, * filters for command keys, * and sends keys. */ int dokey(c) register int c; { char *xxip; char s[80]; int i; switch (c) { case A_C: /* open capture file */ if(!tw->capon) { kb_puts("\r\nEnter capture file name, ESC to abort: "); s[0] = 0; while(0>=(i = kb_gets(s,sizeof(s)-1,1))) suspnd(0); if(i!=27 && s[0]!=0) { kb_nline(); if((tw->capfp = rtopen(s,"wn",1,1)) != NULL) { tw->capon = 1; stptok(tw->capfp->io_name, tw->capfil, 15, "["); strlwr(tw->capfil); } } } if(tw->capon) { kbprintf("\r\nCapture file %s is open.", tw->capfil); } kb_nline(); c = 0; break; case A_D: /* close capture file */ if(tw->capon) { rtclose(tw->capfp); tw->capon = 0; kbprintf("\r\nCapture file %s is closed.\r\n", tw->capfil); } else { kb_puts("\r\nCapture file not open.\r\n"); } c = 0; break; case A_F: /* an ftp command */ xxip = skt->tcpout.i.ipsource; sprintf(s,"ftp %d.%d.%d.%d\r\n", *(xxip+0)&0xFF, *(xxip+1)&0xFF, *(xxip+2)&0xFF, *(xxip+3)&0xFF); skwrite(cnctskt,s,strlen(s)); c=0; break; case A_H: /* help display */ printtxt(hlptxt); c = 0; break; case A_I: /* my internet address */ case A_J: /* their internet address */ if(c==A_I) { xxip = skt->tcpout.i.ipsource; } else { xxip = skt->tcpout.i.ipdest; } sprintf(s,"%d.%d.%d.%d", *(xxip+0)&0xFF, *(xxip+1)&0xFF, *(xxip+2)&0xFF, *(xxip+3)&0xFF); skwrite(cnctskt,s,strlen(s)); c = 0; break; case A_O: /* abort output */ skwrite(cnctskt,"\377\365",2); skempty(cnctskt); c = 0; break; case A_Q: /* are you there? */ skwrite(cnctskt,"\377\366",2); c = 0; break; case A_S: /* skip to end */ skempty(cnctskt); c = 0; break; case A_X: /* close the connection */ kb_puts("\r\nClose the connection? (Y/N) "); kb_out(c = kb_gchar()); if(tolower(c)=='y') { kb_puts("\r\n Attempting to close . . ."); skptuev(ABORTCLASS,USERABORT,cnctskt); } kb_nline(); c = 0; break; case A_Y: /* interrupt */ skwrite(cnctskt,"\377\364",2); skempty(cnctskt); c = 0; break; case A_BRK: /* abort Telnet */ kb_puts("\r\nAbort the connection? (Y/N) "); kb_out(c = kb_gchar()); kb_nline(); if(tolower(c)=='y') { if(tw->capon) { rtclose(tw->capfp); /* close the capture file */ tw->capon = 0; } skclose(cnctskt); skrelease(cnctskt,1); return(A_BRK); } c = 0; break; default: break; } if(c>0) skwchar(cnctskt,c); return(c); } /* * This is the error print routine for TSXUTL.C * It will be called only if there is an internal error */ VOID lsterr() { if(*errstr) { kb_puts(errstr); kb_nline(); errstr[0] = '\0'; } } /* * General looping question routine * loops until a response is given * returns 1 on ABORT * else 0 */ static int question(cstr,clen,qstr) char *cstr,*qstr; int clen; { while(!(*(stpblk(cstr)))) { /* * get arg from user */ kb_puts(qstr); if(rtresp(cstr,clen)) return(1); } return(0); } /* * Routine to get a keyboard response * returns 1 on ABORT * else 0 */ int rtresp(st,ln) char *st; int ln; { return((keygets(st,ln,1)==ABORT) ? 1 : 0); } /* * keygets * * read a line from the keyboard * returns ABORT if keyboard input aborted * or non-zero on success */ int keygets(str,lim,echo) register char *str; /* where to put the line */ int lim,echo; /* max chars to read, echo? */ { register char *save; int c; save = str; /* beginning of line */ *save = '\0'; if(fndbrk) { fndbrk = 0; kb_puts("^C\r\n"); return(ABORT); } while(1) { /* * build string from keyboard */ c = kb_gets(str,lim,echo); if(1 <= c && c <= 31) { kb_nline(); return(strlen(save)); } /* * check for abort */ if(fndbrk) { fndbrk = 0; *save = '\0'; kb_puts("^C\r\n"); return(ABORT); } suspnd(0); } } /* * getword: remove a word from a string. Things within quotes are * assumed to be one word. * return TRUE on success, FALSE on end of string */ static int getword(string,word) char *string; register char *word; { register char *p; register int i; char *q; i = 0; /* * skip leading blanks */ p = stpblk(string); if(!(*p)) { /* * no words in string */ word[0] = '\0'; return(FALSE); } if(*p == '\"') { /* * word delimited by quotes */ while(p[++i] && p[i] != '\"') word[i-1] = p[i]; word[i-1] = '\0'; if(!p[i]) { /* * Missing \". Assumed at end of string. */ } else { i++; } q = p+i; } else { /* * get word, max len 79 */ q = stptok(p, word, 79, " \t\r\n"); } /* * remove trailing blanks */ p = stpblk(q); /* * remove extracted stuff */ strcpy(string,p); return(TRUE); } static char *stptok( p, toword, ilen, delim) register char *p; char *toword; int ilen; char *delim; { register char *adv; register int i; int j,end; adv = toword; end = 0; j = strlen(delim); do { for(i=0; i= (toword+ilen-1)) end++; *adv++=*p++; } } while(!end); *adv='\0'; return(p); } static char *stpblk(ch) register char *ch; { while(*ch == ' ' || *ch == '\t') ch++; return(ch); } static VOID strlwr(st) register char *st; { while(*st) { *st = tolower(*st); *st++; } } /* * chkusr * * Check the password file for the user/password * combination. An inaccessable password file * results in an invalid return. * * If the user/password are validated and * the user has the rquired privelege, * then a valid return is made. * * Returns valid(0)/invalid(1) */ int chkusr() { FILE *fp; struct userblock user; char username[USERPASSLEN+2]; char password[USERPASSLEN+2]; char command[100]; char word[100]; /* * username */ if(question(command,100,"Username: ")) return(1); getword(command,word); username[0] = '\0'; strncat(username,word,USERPASSLEN); strlwr(username); /* * password */ if(!(*stpblk(command))) { kb_puts("Password: "); if(keygets(command,100,0) == ABORT) return(1); } getword(command,word); password[0] = '\0'; strncat(password,word,USERPASSLEN); strlwr(password); /* * Check username / password file */ if(NULL==(fp = rtopen(pass,"rn",0,0))) { return(1); } while (NULL != fread(&user,sizeof(struct userblock),1,fp)) { /* * does username / password check ? */ if(!strncmp(username,&user.username,USERPASSLEN) && (user.userflag[0]&PASSNOTREQUIRED || Scompass(password,&user.password)) ) { rtclose(fp); /* * Check CNCT privileges */ if(!(user.userflag[1] & LCNCT_PRIV)) { kb_puts("No Privilege for CNCT\r\n"); return(1); } /* * User valid */ return(0); } } kb_puts("Invalid Username / Password.\r\n"); rtclose(fp); return(1); } /* * Scompass ( ps, en ) * * Compute and check the encrypted password */ int Scompass(ps,en) char *ps,*en; { int i,ck; char *p,c; ck = 0; p = ps; /* * checksum the string */ while (*p) ck += *p++; c = ck; /* * XOR with checksum */ i = USERPASSLEN; while (i--) { if((((*ps ^ c)|32)&127)!=*en) return(0); /* * increment checksum to hide length */ if(*ps) { ps++; } else { c++; } en++; } return(1); } /* * printout text */ VOID printtxt(txt) char **txt; { char **dp; for (dp = txt; *dp; dp++) { kb_puts(*dp); kb_nline(); } }