home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / applic / ncsa / Mac / Telnet2.6 / prerelease / d5 / Telnet 2.6.1d5.src.sit.hqx / Telnet 2.6.1d5 src / source / parse / authencrypt.c next >
Encoding:
C/C++ Source or Header  |  1995-01-07  |  10.3 KB  |  455 lines

  1. /*
  2.  * Authencrypt.c
  3.  * Authentication module for NCSA/Telnet and Brown tn3270.
  4.  */
  5.  
  6.  
  7. #ifdef MPW
  8. #pragma segment Parse
  9. #endif
  10.  
  11. #include <stdio.h>
  12. #include <string.h>
  13.  
  14. #include "TelnetHeader.h"
  15.  
  16. #include <Devices.h>
  17. #include <Files.h>
  18. #include <Folders.h>
  19. #include <Gestalt.h>
  20. #include <Memory.h>
  21. #include <OSUtils.h>
  22. #include <Resources.h>
  23. #include <StdLib.h>
  24. #include <Types.h>
  25.  
  26. #include "tnae.h"
  27. #include "authencrypt.h"
  28.  
  29. #include "authencrypt.proto.h"
  30.  
  31. #define NAUTHTYPES    10                    /* Max number of auth types */
  32.  
  33. struct codemodule *authmodules = 0;    /* list of authentication code modules */
  34.  
  35. static char nullbuf[] = {IAC, SB, OPT_AUTHENTICATION, TNQ_IS, AUTH_NULL, 
  36.                              AUTH_CLIENT_TO_SERVER|AUTH_HOW_ONE_WAY, IAC, SE};
  37.  
  38. #ifdef powerc
  39. enum {
  40.     uppModule = kCStackBased
  41.         | RESULT_SIZE(SIZE_CODE(sizeof(long)))
  42.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  43.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr)))
  44. };
  45. #endif
  46.  
  47. #ifdef __MWERKS__
  48. #pragma profile off
  49. #endif
  50.  
  51. static    void    scanFolder(short vRef, long dirID);
  52.  
  53. /*
  54.  * auth_encrypt_init
  55.  * Initialize processing for auth/encrypt options.
  56.  * Find all the modules that support auth/encrypt and add them to our
  57.  * typepairs and modules table. Load those modules and initialize them.
  58.  *
  59.  * Return true if any auth module found.
  60.  */
  61. Boolean auth_encrypt_init ()
  62. {
  63.     short vref;
  64.     long dirid = 0, fold;
  65.     SysEnvRec theWorld;
  66.  
  67.     /*
  68.      * Find and load/initialize files with code modules.
  69.      * First, Try to find the Extensions folder, else use the system folder.
  70.      */
  71.     if (Gestalt('fold', &fold)  || 
  72.         ((fold & 1) != 1) ||
  73.         FindFolder(kOnSystemDisk, kExtensionFolderType, false, &vref, &dirid)) {
  74.         if (SysEnvirons (1, &theWorld) == 0)
  75.             vref = theWorld.sysVRefNum;
  76.         else
  77.             vref = -1;
  78.     }
  79.  
  80.     scanFolder(vref, dirid);
  81.     
  82.     // Now scan the folder that Telnet lives in
  83.     scanFolder(TelInfo->ApFolder.vRefNum, TelInfo->ApFolder.parID);
  84.     
  85.     if (authmodules)
  86.         return true;
  87.     return false;
  88. }
  89.  
  90. static    void    scanFolder(short vRef, long dirID)
  91. {
  92.     short            i;
  93.     HParamBlockRec    pb;
  94.     Str255            name;
  95.     OSErr            s;
  96.     
  97.     for (i = 1; ; i++ ) {
  98.         pb.fileParam.ioCompletion = 0;
  99.         pb.fileParam.ioVRefNum = vRef;
  100.         pb.fileParam.ioFVersNum = 0;
  101.         pb.fileParam.ioFDirIndex = i;
  102.         pb.fileParam.ioDirID = dirID;
  103.         pb.fileParam.ioNamePtr = name;
  104.         if ((s = PBHGetFInfo(&pb, false)) != noErr)
  105.             break;
  106.  
  107.         /*    Check for module types that we are interested in. */
  108.         if (pb.fileParam.ioFlFndrInfo.fdType == moduleType) {
  109.             loadCode(&pb, dirID, name, authType, &authmodules);
  110.             }
  111.         }
  112. }
  113. void loadCode (HParamBlockRec *pb, long dirid, Str255 name, OSType type, codemodule **header)
  114. {
  115.     int i;
  116.     short rf, oldrf;
  117.     struct codemodule *code = 0;
  118.     Handle h;
  119.  
  120.     oldrf = CurResFile();
  121.     rf = HOpenResFile(pb->fileParam.ioVRefNum, dirid, name, fsRdPerm);    
  122.     if (rf == -1)
  123.         return;
  124.     SetResLoad(true);
  125.     
  126.     /*
  127.      * Find all resources of indicated type.
  128.      */
  129.     for (i = 1; ; i++) {
  130.         if (!((h = Get1IndResource(type, i))))
  131.             break;
  132.  
  133.         if (code = (struct codemodule *)NewPtrClear(sizeof(struct codemodule))) {
  134.             DetachResource(h); 
  135.             HNoPurge(h);
  136.             HLockHi(h);
  137.             code->entry = (module)*h;
  138.             /*
  139.              * Initialize the module.
  140.              * It should preset the type/pairs list and return the number of
  141.              * pairs entered.
  142.              */
  143. #ifdef powerc
  144.             code->npairs = CallUniversalProc((UniversalProcPtr)code->entry, uppModule, 
  145.                                              TNFUNC_INIT_CODE, &code->pairs);
  146.             code->encryptok = CallUniversalProc((UniversalProcPtr)code->entry, uppModule, 
  147.                                                 TNFUNC_QUERY_ENCRYPT, 0);
  148. #else
  149.             code->npairs = (*code->entry)(TNFUNC_INIT_CODE, &code->pairs);
  150.             code->encryptok = (*code->entry)(TNFUNC_QUERY_ENCRYPT, 0);
  151. #endif
  152.             qlink(header, code);
  153.         } else
  154.             ReleaseResource(h);
  155.     }
  156.     CloseResFile(rf);  /* ddd for debugging with The Debugger ***/
  157.     UseResFile(oldrf);
  158. }
  159.  
  160.  
  161. /*
  162.  * auth_suboption
  163.  * Called by the Telnet client when an authentication sub-option is received.
  164.  * The reply option (if any) is placed into sendbuffer and *sendlength adjusted
  165.  * by the amount of data placed into sendbuffer.
  166.  */
  167. void auth_suboption (tnParams **aedata, unsigned char *subbuffer, long sublength, unsigned char *sendbuffer, unsigned long *sendlength, char *cname, Boolean hisencrypt, Boolean myencrypt)
  168. {
  169.     int i;
  170.     OSErr s;
  171.     unsigned short pair;
  172.     unsigned char *cp, *buflimit;
  173.     struct codemodule *code = 0;
  174.     tnParams *tn;                        /* temp params struct */
  175.     
  176.     buflimit = subbuffer + sublength;
  177.  
  178.     /*
  179.      * Initialize session's tnParams if not initialized yet.
  180.      * Return null auth if no memory and TNQ_SEND.
  181.      */
  182.     if (!(*aedata)) {
  183.         *aedata = (tnParams *)NewPtrClear(sizeof(tnParams));
  184.         if (!(*aedata)) {
  185.             if (subbuffer[SB_SUBOPTION] == TNQ_SEND) {
  186.                 BlockMove((Ptr)nullbuf, (Ptr)sendbuffer, sizeof(nullbuf));
  187.                 *sendlength -= sizeof(nullbuf);
  188.             }
  189.             return;
  190.         }
  191.     }
  192.     tn = *aedata;
  193.     
  194.     switch (subbuffer[SB_SUBOPTION]) {
  195.     case TNQ_IS:
  196.     case TNQ_NAME:
  197.         /* The client should not get one of these */
  198.         break;
  199.  
  200.     case TNQ_SEND:
  201.         /*
  202.          * For telnet clients, the buffer contains:
  203.          * AUTHENTICATION SEND type modifier [type modifier] [...] IAC SE
  204.          * DDD is IAC SE in the buffer???
  205.          * We scan the type/modifier pairs until we find one we can do. 
  206.          * Since they are are in priority order, the  first one we
  207.          * find that we can do wins.
  208.          */
  209.         for (cp = &subbuffer[SB_TYPE]; cp < buflimit; cp += 2) {
  210.             pair = (cp[0] << 8) | cp[1];
  211.             for (code = authmodules; code; code = code->next) {
  212.                 for (i = 0; i < code->npairs; i++)  {
  213.                     if (pair == code->pairs[i])
  214.                         goto brk;
  215.                 }
  216.             }
  217.         }
  218.     brk:
  219.         if (!code) {
  220.             /*
  221.              * If no methods match, send null authentication.
  222.              */
  223.             BlockMove((Ptr)nullbuf, (Ptr)sendbuffer, sizeof(nullbuf));
  224.             *sendlength -= sizeof(nullbuf);
  225.             return;
  226.         }
  227.  
  228.         /*
  229.          * If no auth data, initialize it now.
  230.          */
  231.         if (!(tn->authdata)) {
  232. #ifdef powerc
  233.             s = CallUniversalProc((UniversalProcPtr)code->entry, uppModule, 
  234.                                   TNFUNC_INIT_SESSION_AUTH, &tn->authdata);
  235.             if ((s == 0) && !tn->encryptdata)
  236.                 s = CallUniversalProc((UniversalProcPtr)code->entry, uppModule, 
  237.                                       TNFUNC_INIT_SESSION_ENCRYPT, &tn->encryptdata);
  238. #else
  239.             s = (*code->entry)(TNFUNC_INIT_SESSION_AUTH, &tn->authdata);
  240.             if ((s == 0) && !tn->encryptdata)
  241.                 s = (*code->entry)(TNFUNC_INIT_SESSION_ENCRYPT, &tn->encryptdata);
  242. #endif
  243.             if (s) {                    /* if no memory, etc */
  244.                 BlockMove((Ptr)nullbuf, (Ptr)sendbuffer, sizeof(nullbuf));
  245.                 *sendlength -= sizeof(nullbuf);
  246.                 return;
  247.             }
  248.             tn->entry = code->entry;
  249.         }
  250.  
  251.         /*
  252.          * Process the SEND option
  253.          */
  254.         tn->subbuffer = subbuffer;
  255.         tn->sublength = sublength;
  256.         tn->sendbuffer = sendbuffer;
  257.         tn->sendlength = sendlength;
  258.         tn->cname = cname;
  259.         tn->hisencrypt = hisencrypt;
  260.         tn->myencrypt = myencrypt;
  261. #ifdef powerc
  262.         s = CallUniversalProc((UniversalProcPtr)tn->entry, uppModule, 
  263.                               TNFUNC_AUTH_SEND, tn);        
  264. #else
  265.         s = (*tn->entry)(TNFUNC_AUTH_SEND, tn);
  266. #endif
  267.         if (s) {
  268.             /* ddd null probably wrong here ??? */
  269.             BlockMove((Ptr)nullbuf, (Ptr)sendbuffer, sizeof(nullbuf));
  270.             *sendlength -= sizeof(nullbuf);
  271.         }
  272.         return;
  273.  
  274.     case TNQ_REPLY:
  275.         /*
  276.          * Process the reply.
  277.          */
  278.         if (!(tn->authdata)) {
  279.             DebugStr("\pauth_suboption: tnq_reply no authdata");
  280.             return;
  281.         }
  282.         tn->subbuffer = subbuffer;
  283.         tn->sublength = sublength;
  284.         tn->sendbuffer = sendbuffer;
  285.         tn->sendlength = sendlength;
  286.         tn->cname = cname;
  287.         tn->hisencrypt = hisencrypt;
  288.         tn->myencrypt = myencrypt;
  289. #ifdef powerc
  290.         s = CallUniversalProc((UniversalProcPtr)tn->entry, uppModule, 
  291.                               TNFUNC_AUTH_REPLY, tn);
  292. #else
  293.         s = (*tn->entry)(TNFUNC_AUTH_REPLY, tn);
  294. #endif
  295.         switch (s) {
  296.         case TNREP_OK:
  297.             return;
  298.  
  299.         case TNREP_AUTH_OK:
  300.             break;
  301.  
  302.         case TNREP_AUTH_ERR:
  303.             break;
  304.         }
  305.         return;
  306.     }
  307. }
  308.  
  309.  
  310. /*
  311.  * encrypt_suboption
  312.  * Called by the Telnet client when an encryption sub-option is received.
  313.  * The reply option (if any) is placed into sendbuffer and *sendlength adjusted
  314.  * by the amount of data placed into sendbuffer.
  315.  */
  316. short encrypt_suboption (tnParams **aedata, unsigned char *subbuffer, long sublength, unsigned char *sendbuffer, unsigned long *sendlength, char *cname, Boolean hisencrypt, Boolean myencrypt)
  317. {
  318.     short s;
  319.     tnParams *tn;
  320.     struct codemodule *code = 0;
  321.             
  322.     /*
  323.      * Initialize session's tnParams if not there. 
  324.      * Return null auth if no memory and TNQ_SEND.
  325.      */
  326.     if (!(*aedata)) {
  327.         *aedata = (tnParams *)NewPtrClear(sizeof(tnParams));
  328.         if (!(*aedata)) {
  329.             return 0;
  330.         }
  331.     }
  332.     tn = *aedata;
  333.  
  334.     if (!tn->encryptdata) {
  335.         for (code = authmodules; code; code = code->next) {
  336.             if (code->encryptok)
  337.                 break;
  338.         }
  339.         if (!code)
  340.             return 0;
  341.  
  342. #ifdef powerc
  343.         s = CallUniversalProc((UniversalProcPtr)code->entry, uppModule, 
  344.                               TNFUNC_INIT_SESSION_ENCRYPT, &tn->encryptdata);
  345. #else
  346.         s = (*code->entry)(TNFUNC_INIT_SESSION_ENCRYPT, &tn->encryptdata);
  347. #endif
  348.         if (s)
  349.             return TNREP_ERROR;
  350.  
  351.         tn->entry = code->entry;
  352.     }
  353.  
  354.     tn->subbuffer = subbuffer;
  355.     tn->sublength = sublength;
  356.     tn->sendbuffer = sendbuffer;
  357.     tn->sendlength = sendlength;
  358.     tn->cname = cname;
  359.     tn->hisencrypt = hisencrypt;
  360.     tn->myencrypt = myencrypt;
  361. #ifdef powerc
  362.     s = CallUniversalProc((UniversalProcPtr)tn->entry, uppModule, 
  363.                           TNFUNC_ENCRYPT_SB, tn);
  364. #else
  365.     s = (*tn->entry)(TNFUNC_ENCRYPT_SB, tn);
  366. #endif
  367.     return s;
  368. }
  369.  
  370.  
  371. unsigned char decrypt (tnParams *tn, long value)
  372. {
  373.     tn->data = value;
  374. #ifdef powerc
  375.     CallUniversalProc((UniversalProcPtr)tn->entry, uppModule, 
  376.                           TNFUNC_DECRYPT, tn);
  377. #else
  378.     (*tn->entry)(TNFUNC_DECRYPT, tn);
  379. #endif
  380.     return (unsigned char)tn->data;
  381. }
  382.  
  383.  
  384. void encrypt (tnParams *tn, unsigned char *buf, long len)
  385. {
  386.     tn->data = len;
  387.     tn->ebuf = buf;
  388. #ifdef powerc
  389.     CallUniversalProc((UniversalProcPtr)tn->entry, uppModule, 
  390.                           TNFUNC_ENCRYPT, tn);
  391. #else
  392.     (*tn->entry)(TNFUNC_ENCRYPT, tn);
  393. #endif
  394. }
  395.  
  396.  
  397. /*
  398.  * qlink
  399.  * Add an entry to the end of a linked list
  400.  */
  401. void qlink (void **flist, void *fentry)
  402. {
  403.     struct dummy {
  404.         struct dummy *next;
  405.     } **list, *entry;
  406.  
  407.     list = flist;
  408.     entry = fentry;
  409.     
  410.     /*
  411.      * Find address of last entry in the list.
  412.      */
  413.     while (*list)
  414.     list = &(*list)->next;
  415.  
  416.     /*
  417.      * Link entry
  418.      */
  419.     *list = entry;
  420.     entry->next = 0;
  421. }
  422.  
  423.  
  424. /*
  425.  * qunlink
  426.  * Remove an entry from linked list
  427.  * Returns the entry or NULL if not found.
  428.  */
  429. void *qunlink (void **flist, void *fentry)
  430. {
  431.     struct dummy {
  432.         struct dummy *next;
  433.     } **list, *entry;
  434.  
  435.     list = flist;
  436.     entry = fentry;
  437.     
  438.     /*
  439.      * Find entry and unlink it
  440.      */
  441.     while (*list) {
  442.         if ((*list) == entry) {
  443.             *list = entry->next;
  444.             return entry;
  445.         }
  446.     
  447.         list = &(*list)->next;
  448.     }
  449.     return NULL;
  450. }
  451.  
  452.  
  453.  
  454.  
  455.