home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / winsock / fingd100 / src / finger.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  11.6 KB  |  461 lines

  1. // Contents ---------------------------------------------------------------
  2. //
  3. //   finger.c  -- a Windows Socket Finger Daemon
  4. //
  5. //   Version 1.0
  6. //
  7. //   Copyright (C) Frederick W. Bent 1994
  8. //   All rights reserved.
  9. //
  10. //
  11. // Description
  12. //
  13. // Ends -------------------------------------------------------------------
  14.  
  15. // History ----------------------------------------------------------------
  16. //
  17. // 6/28/94  1.0  Fred Bent    First release
  18. //
  19. // Ends -------------------------------------------------------------------
  20.  
  21. // Legal Stuff ------------------------------------------------------------
  22. //
  23. // Permission to use, modify, and distribute this software and its
  24. // documentation for any purpose and without fee is hereby granted,
  25. // provided that the above copyright notice appears in all copies and
  26. // that both that copyright notice and this permission notice appear in
  27. // supporting documentation.  The author makes no claims as to the
  28. // suitability of this software and documentation for any purpose.
  29. //
  30. // Legal Stuff Ends -------------------------------------------------------
  31.  
  32.  
  33. // Interface Dependencies -------------------------------------------------
  34.  
  35. #define STRICT
  36.  
  37. #include <windows.h>
  38. #include <windowsx.h>
  39. #include <winsock.h>
  40. #include <string.h>
  41. #include "fingerd.h"
  42. #include "file.h"
  43.  
  44.  
  45. // Function
  46.  
  47.     BOOL    IllegalRequest(LPSTR szUsername)
  48.  
  49. // Summary ----------------------------------------------------------------
  50. //
  51. //    Check the requested user to verify that it does not contain any
  52. //    thing that would indicate that it is a request that would
  53. //    cause a directory change.
  54. //
  55. // Parameters
  56. //
  57. //      szUsername
  58. //
  59. //    The user id that we have been requested to return information about
  60. //
  61. // Return
  62. //
  63. //    BOOL    Returns TRUE if the name would cause a directory
  64. //        change because it contains a backslash.
  65. //
  66. // Ends -------------------------------------------------------------------
  67.  
  68.     {
  69.         if ( _fstrstr( szUsername, ".." ) != NULL ) return(TRUE);
  70.         if ( lstrchr( szUsername, '\\') != NULL ) return(TRUE);
  71.         if ( lstrchr( szUsername, ':') != NULL ) return(TRUE);
  72.  
  73.         return(FALSE);
  74.     }
  75.  
  76.  
  77.     LPSTR    RemoveIAC(LPSTR lpszString)
  78.     {
  79.         LPSTR    temp;
  80.  
  81.         temp = lpszString;
  82.  
  83.         while( *temp == '\xFF')    // IAC
  84.         {
  85.             temp++;
  86.             if ( *temp != '\xFF' )
  87.             {
  88.                 temp++;    // WILL
  89.                 temp++;    // option code
  90.             }
  91.         }
  92.  
  93.         return temp;
  94.     }
  95.  
  96. // Server Function
  97.  
  98.     int    fingerSendFile(LPCLIENT lpClient)
  99.  
  100. // Summary ----------------------------------------------------------------
  101. //
  102. //    Send the file down the socket to the client.
  103. //
  104. // Parameters
  105. //
  106. //      lpClient
  107. //
  108. //    The client that we are sending the file to
  109. //
  110. // Return
  111. //
  112. //    BOOL    Returns TRUE if WSAEWOULDBLOCK, or FALSE if error
  113. //
  114. // Ends -------------------------------------------------------------------
  115.  
  116.     {
  117.         int    nChars;
  118.         int    fifoStart;
  119.         HFILE     hfFile;
  120.         LPSTR      szBuffer;
  121.         SOCKET  sSocket;
  122.         UINT    iBufSize;
  123.         int    nBytesSent;
  124.         fd_set    fdSet;
  125.         struct timeval tm;
  126.  
  127.         
  128.         if (lpClient == NULL) return(TRUE);
  129.  
  130.         /* Trap case of nothing to send yet */
  131.         if ( ( lpClient->iState != STATE_SENDING ) &&
  132.              ( lpClient->iState != STATE_SEND_TIME ) ) return(TRUE);
  133.  
  134.         hfFile = lpClient->hfFile;
  135.  
  136.         szBuffer = lpClient->lpOutputBuffer;
  137.         sSocket = lpClient->sSocket;
  138.  
  139.         /*
  140.          * Should be half since the netascii conversion
  141.          * may double the size of the buffer.
  142.          */
  143.         iBufSize = (lpClient->iOutputSize) >> 1;
  144.         nBytesSent = 0;
  145.  
  146.         if (( lpClient->iState == STATE_SEND_TIME ) && (lpClient->fifoOutputStart == 0))
  147.         {
  148.             nChars = FillInTheBlanks( lpClient->lpInputBuffer, (LPSTR) szBuffer, iBufSize, hfFile);
  149. //            lpClient->iState = STATE_SENDING;
  150.             lpClient->fifoOutputStop = nChars;
  151.             lpClient->fifoOutputStart = nChars;
  152.         }
  153.  
  154.         /* Trap case of nothing to send */
  155.         if (( hfFile == HFILE_ERROR ) && ( lpClient->iState == STATE_SENDING ))
  156.         {
  157.             lpClient->iState = STATE_FINISHED;
  158.             return(FALSE);
  159.         }
  160.  
  161. #ifndef    NDEBUG
  162.         FD_ZERO(&fdSet);
  163.         FD_SET(sSocket,&fdSet);
  164.  
  165.         tm.tv_sec = 0L;
  166.         tm.tv_usec = 0L;
  167.  
  168.         /* Can we send on this socket? */
  169.         if ( select(0,NULL,&fdSet,NULL,&tm) == SOCKET_ERROR ) return(FALSE);
  170.  
  171.         if ( !FD_ISSET(sSocket,&fdSet) )
  172.         {
  173. //            OkMsgBox("clientSendFile", "Socket is not writeable!");
  174.         }
  175. #endif
  176.  
  177.         do {
  178.             /* Is our buffer empty? If so the get some more text... */
  179.  
  180.             if ( lpClient->fifoOutputStop == 0 )
  181.             {
  182.                 /*
  183.                  * Read the bytes from the file and the convert
  184.                  * the buffer into netascii, which may double
  185.                  * the nChars.
  186.                  */
  187.                 nChars = _lread(hfFile, (LPSTR) szBuffer, iBufSize);
  188.                 if ( nChars != HFILE_ERROR )
  189.                                 {
  190.                     nChars = netascii((LPSTR)szBuffer, nChars);
  191.                     if ( nChars == -1 )
  192.                     {
  193.                         lpClient->iState = STATE_FINISHED;
  194.                         fingerLog(DEBUG_OFF, IDS_REQUEST_ERR, (LPSTR) "fingerSendFile");
  195.                         return(FALSE);
  196.                     }
  197.                 }
  198.  
  199.                 lpClient->fifoOutputStop = nChars;
  200.                 lpClient->fifoOutputStart = nChars;
  201.  
  202.                 if ( nChars == HFILE_ERROR )
  203.                 {
  204.                     lpClient->iState = STATE_FINISHED;                               
  205.                     fingerLog(DEBUG_OFF, IDS_FILE_ERR);
  206.                     return(FALSE);
  207.                 }
  208.             } else { nChars = lpClient->fifoOutputStop; }
  209.  
  210.             /* OK, send the stuff in the buffer to the client */
  211.  
  212.             fifoStart = lpClient->fifoOutputStart - nChars;
  213.             if (nChars > 0)    // Cannot send 0 bytes - WSAEINVAL
  214.                 nBytesSent = send(sSocket, (LPSTR) &szBuffer[fifoStart], nChars, 0);
  215.             else nBytesSent = 0;
  216.  
  217.             /*
  218.              * Oh no! A Winsock error occured!
  219.              *
  220.              * WSAEWOULDBLOCK - Means we should wait until a new FD_READ
  221.              *             is posted, so don't panic.
  222.              */
  223.  
  224.             if ( nBytesSent == SOCKET_ERROR )
  225.             {
  226.                 lpClient->iExtErr = WSAGetLastError();
  227.                 lpClient->iState = STATE_SENDING;
  228.  
  229.                 if ( lpClient->iExtErr == WSAEWOULDBLOCK )
  230.                 {
  231. #ifndef NDEBUG
  232. //                    OkMsgBox("clientSendFile", "Socket Error: WSAEWOULDBLOCK (%d)", nChars);
  233. #endif
  234.                     return(TRUE);    // OK, we'll wait for FD_READ
  235.                 } else {
  236.                     lpClient->iState = STATE_WSERROR;
  237.                     DisplayWSError("Sending");
  238.                     return(FALSE);
  239.                 }
  240.  
  241.             } else {
  242.                 UpdateDisplay((LPSTR) &szBuffer[fifoStart], nBytesSent);
  243.                 lpClient->fifoOutputStop -= nBytesSent;
  244.             }
  245.  
  246.             /* Finished sending info, now send .plan */
  247.             if ((lpClient->fifoOutputStop == 0) && (lpClient->iState == STATE_SEND_TIME))
  248.             {
  249.                 if (hfFile == HFILE_ERROR)
  250.                 {
  251.                     nChars = 0;
  252.                     nBytesSent = 0;
  253.                     lpClient->iState = STATE_FINISHED;
  254.                 } else
  255.                     lpClient->iState = STATE_SENDING;
  256.             }
  257.  
  258.  
  259.             /* Reached EOF and sent all of the bytes? */
  260.  
  261.             if ( ( nChars == 0 ) && ( nChars == nBytesSent ) )
  262.             {
  263.                 /*
  264.                  * These must come BEFORE the call to OkMsgBox
  265.                  * since this will cause the program to yeild
  266.                  * and more FD_WRITE messages will get
  267.                  * posted.
  268.                  */
  269.                 lpClient->iState = STATE_FINISHED;
  270.                 lpClient->iExtErr = 0;
  271. #ifndef NDEBUG
  272. //                OkMsgBox("clientSendFile", "Finger is complete.");
  273. #endif
  274.                 FingerFinished();
  275.             }
  276.  
  277.         } while ( lpClient->iState == STATE_SENDING );
  278.  
  279.         return(FALSE);
  280.     }
  281.  
  282.  
  283. // Server function
  284.  
  285.     BOOL    fingerServer(LPCLIENT lpClient)
  286.  
  287. // Summary ----------------------------------------------------------------
  288. //
  289. //    This is the "guts" of the text server.  It will get the user that
  290. //    the client wishes to finger.  If there is no user then will
  291. //    return the default file.
  292. //
  293. // Parameters
  294. //
  295. //      lpClient    The client that is going to be served.
  296. //
  297. // Return
  298. //
  299. //    BOOL    Returns TRUE if error and client should be destroyed
  300. //
  301. // Ends -------------------------------------------------------------------
  302.  
  303.     {
  304.         int    nChars;
  305.         int    iErr;
  306.         int    nLen;
  307.         int    fifoStart;
  308.                 BOOL    bSnarking;
  309.                 SOCKET    sSocket;
  310.         LPSTR    szFile = NULL;
  311.         LPSTR    str1 = NULL;
  312.                 LPSTR    str2 = NULL;
  313.         OFSTRUCT ofOpenBuff;
  314.         HGLOBAL    hInput;
  315.         HGLOBAL hTempFile;
  316.         LPSTR    lpInput = NULL;
  317.         LPSTR    lpTempFile = NULL;
  318.  
  319.  
  320.         // Perform a sanity check
  321.         if (lpClient == NULL) return(FALSE);
  322.  
  323.         // Make things easier
  324.         szFile = lpClient->lpInputBuffer;
  325.         fifoStart = lpClient->fifoInputStart;
  326.         sSocket = lpClient->sSocket;
  327.  
  328.         // Get the request
  329.         nChars = recv(sSocket, &szFile[fifoStart], (lpClient->iInputSize - fifoStart), 0);
  330.  
  331.         if ( nChars == SOCKET_ERROR )
  332.         {
  333.             lpClient->iExtErr = WSAGetLastError();
  334.             if ( lpClient->iExtErr != WSAEWOULDBLOCK )
  335.             {
  336.                 lpClient->iState = STATE_WSERROR;
  337.                 return(TRUE);
  338.             }
  339.             else szFile[fifoStart] = '\0';
  340.         }
  341.         fifoStart += nChars;
  342.  
  343.         /* Did we get everything yet? <CRLF> */
  344.         if ( (str2 = lstrchr(szFile, '\n')) != NULL )
  345.             *str2 = '\0';
  346.         if ( (str1 = lstrchr(szFile, '\r')) != NULL )
  347.             *str1 = '\0';
  348.  
  349.         szFile = RemoveIAC(szFile);
  350.  
  351.         /*
  352.          * Now, have we already started processing request?
  353.          */
  354.         if ( lpClient->iState != STATE_WAIT_FOR_USER ) return(FALSE);
  355.  
  356.         // OK, we have gotten the request...
  357.         if ( ( str1 != NULL ) && ( str2 != NULL ) )
  358.         {
  359.             fingerLog(DEBUG_HIGH, IDS_RECV_S, (LPSTR)szFile, sSocket);
  360.  
  361.             if ( lpClient->hfFile == HFILE_ERROR)
  362.             {
  363.                 if ( ( lstrlen(szFile) == 0) || ( bOnlySnark ) )
  364.                 {
  365.                     bSnarking = TRUE;
  366.                     lpClient->hfFile = OpenFile(szLocalFile, &ofOpenBuff, OF_SHARE_DENY_WRITE);
  367.                     if ( lpClient->hfFile == HFILE_ERROR )
  368.                         lpClient->iState = STATE_FINISHED;
  369.                     else
  370.                         lpClient->iState = STATE_SENDING;
  371.                 } else if ( !IllegalRequest(szFile) )
  372.                 {
  373.                     bSnarking = FALSE;
  374.                     hInput = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, MAX_PATH);
  375.                     if ( hInput == NULL ) return(TRUE);
  376.  
  377.                     /* Now get a pointer to it */
  378.                     lpInput = GlobalLock(hInput);
  379.                     if (lpInput == NULL )
  380.                     {
  381.                         GlobalFree(hInput);
  382.                         return(TRUE);
  383.                     }
  384.  
  385.                     hTempFile = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, MAX_FNAME);
  386.                     if ( hTempFile == NULL )
  387.                     {
  388.                         GlobalUnlock(hInput);
  389.                         GlobalFree(hInput);
  390.                         return(TRUE);
  391.                     }
  392.  
  393.                     /* Now get a pointer to it */
  394.                     lpTempFile = GlobalLock(hTempFile);
  395.                     if (lpTempFile == NULL )
  396.                     {
  397.                         GlobalUnlock(hInput);
  398.                         GlobalFree(hInput);
  399.                         GlobalFree(hTempFile);
  400.                         return(TRUE);
  401.                     }
  402.  
  403.                     lstrcpy(lpInput, (LPSTR)szFileDir);
  404.                     lstrcat(lpInput, "\\");
  405.  
  406.                     if ( ( lstrlen(szFile) + lstrlen(lpInput) + 14 ) < MAX_PATH )
  407.                     {
  408.                         lstrcat(lpInput, szFile);
  409.                         lstrcat(lpInput, "\\USERINFO.INI");
  410.  
  411.                         lpClient->hfFile = OpenFile(lpInput, &ofOpenBuff, OF_EXIST);
  412.  
  413.                         if ( lpClient->hfFile != HFILE_ERROR )
  414.                         {
  415.                             GetPrivateProfileString( "FingerInfo"
  416.                                 , "Plan"
  417.                                 , "FINGER"
  418.                                 , lpTempFile
  419.                                 , MAX_FNAME
  420.                                 , (LPSTR) lpInput );
  421.  
  422.                             if (IllegalRequest(lpTempFile))
  423.                             {
  424.                                 lstrcpy(lpTempFile, "FINGER");
  425.                             }
  426.  
  427.                             lstrcpy(lpInput, (LPSTR)szFileDir);
  428.                             lstrcat(lpInput, "\\");
  429.                             lstrcat(lpInput, szFile);
  430.                             lstrcat(lpInput, "\\");
  431.                             lstrcat(lpInput, lpTempFile);
  432.  
  433.                             lpClient->hfFile = OpenFile(lpInput, &ofOpenBuff, OF_SHARE_DENY_WRITE);
  434.                             lstrcpy(szFile, lpInput);
  435.                             fifoStart = lstrlen(szFile);
  436.                             lpClient->iState = STATE_SEND_TIME;
  437.                         } else {
  438.                             lpClient->iState = STATE_FINISHED;
  439.                         }
  440.                     } else {
  441.                         fingerLog(DEBUG_OFF, IDS_REQUEST_ERR, (LPSTR)"fingerServer");
  442.                     }
  443.  
  444.                     GlobalUnlock(hInput);
  445.                     GlobalFree(hInput);
  446.                     GlobalUnlock(hTempFile);
  447.                     GlobalFree(hTempFile);
  448.                 }
  449.  
  450.                 /* There is no matching user */
  451.             }
  452.             lpClient->fifoInputStart = fifoStart;
  453.  
  454.         } else { // We have not gotten the complete request yet...
  455.             lpClient->fifoInputStart = fifoStart;
  456.         }
  457.  
  458.                 if ( lpClient->iState == STATE_FINISHED ) return(TRUE);
  459.         else return(FALSE);
  460.     }
  461.