home *** CD-ROM | disk | FTP | other *** search
- // Contents ---------------------------------------------------------------
- //
- // finger.c -- a Windows Socket Finger Daemon
- //
- // Version 1.0
- //
- // Copyright (C) Frederick W. Bent 1994
- // All rights reserved.
- //
- //
- // Description
- //
- // Ends -------------------------------------------------------------------
-
- // History ----------------------------------------------------------------
- //
- // 6/28/94 1.0 Fred Bent First release
- //
- // Ends -------------------------------------------------------------------
-
- // Legal Stuff ------------------------------------------------------------
- //
- // Permission to use, modify, and distribute this software and its
- // documentation for any purpose and without fee is hereby granted,
- // provided that the above copyright notice appears in all copies and
- // that both that copyright notice and this permission notice appear in
- // supporting documentation. The author makes no claims as to the
- // suitability of this software and documentation for any purpose.
- //
- // Legal Stuff Ends -------------------------------------------------------
-
-
- // Interface Dependencies -------------------------------------------------
-
- #define STRICT
-
- #include <windows.h>
- #include <windowsx.h>
- #include <winsock.h>
- #include <string.h>
- #include "fingerd.h"
- #include "file.h"
-
-
- // Function
-
- BOOL IllegalRequest(LPSTR szUsername)
-
- // Summary ----------------------------------------------------------------
- //
- // Check the requested user to verify that it does not contain any
- // thing that would indicate that it is a request that would
- // cause a directory change.
- //
- // Parameters
- //
- // szUsername
- //
- // The user id that we have been requested to return information about
- //
- // Return
- //
- // BOOL Returns TRUE if the name would cause a directory
- // change because it contains a backslash.
- //
- // Ends -------------------------------------------------------------------
-
- {
- if ( _fstrstr( szUsername, ".." ) != NULL ) return(TRUE);
- if ( lstrchr( szUsername, '\\') != NULL ) return(TRUE);
- if ( lstrchr( szUsername, ':') != NULL ) return(TRUE);
-
- return(FALSE);
- }
-
-
- LPSTR RemoveIAC(LPSTR lpszString)
- {
- LPSTR temp;
-
- temp = lpszString;
-
- while( *temp == '\xFF') // IAC
- {
- temp++;
- if ( *temp != '\xFF' )
- {
- temp++; // WILL
- temp++; // option code
- }
- }
-
- return temp;
- }
-
- // Server Function
-
- int fingerSendFile(LPCLIENT lpClient)
-
- // Summary ----------------------------------------------------------------
- //
- // Send the file down the socket to the client.
- //
- // Parameters
- //
- // lpClient
- //
- // The client that we are sending the file to
- //
- // Return
- //
- // BOOL Returns TRUE if WSAEWOULDBLOCK, or FALSE if error
- //
- // Ends -------------------------------------------------------------------
-
- {
- int nChars;
- int fifoStart;
- HFILE hfFile;
- LPSTR szBuffer;
- SOCKET sSocket;
- UINT iBufSize;
- int nBytesSent;
- fd_set fdSet;
- struct timeval tm;
-
-
- if (lpClient == NULL) return(TRUE);
-
- /* Trap case of nothing to send yet */
- if ( ( lpClient->iState != STATE_SENDING ) &&
- ( lpClient->iState != STATE_SEND_TIME ) ) return(TRUE);
-
- hfFile = lpClient->hfFile;
-
- szBuffer = lpClient->lpOutputBuffer;
- sSocket = lpClient->sSocket;
-
- /*
- * Should be half since the netascii conversion
- * may double the size of the buffer.
- */
- iBufSize = (lpClient->iOutputSize) >> 1;
- nBytesSent = 0;
-
- if (( lpClient->iState == STATE_SEND_TIME ) && (lpClient->fifoOutputStart == 0))
- {
- nChars = FillInTheBlanks( lpClient->lpInputBuffer, (LPSTR) szBuffer, iBufSize, hfFile);
- // lpClient->iState = STATE_SENDING;
- lpClient->fifoOutputStop = nChars;
- lpClient->fifoOutputStart = nChars;
- }
-
- /* Trap case of nothing to send */
- if (( hfFile == HFILE_ERROR ) && ( lpClient->iState == STATE_SENDING ))
- {
- lpClient->iState = STATE_FINISHED;
- return(FALSE);
- }
-
- #ifndef NDEBUG
- FD_ZERO(&fdSet);
- FD_SET(sSocket,&fdSet);
-
- tm.tv_sec = 0L;
- tm.tv_usec = 0L;
-
- /* Can we send on this socket? */
- if ( select(0,NULL,&fdSet,NULL,&tm) == SOCKET_ERROR ) return(FALSE);
-
- if ( !FD_ISSET(sSocket,&fdSet) )
- {
- // OkMsgBox("clientSendFile", "Socket is not writeable!");
- }
- #endif
-
- do {
- /* Is our buffer empty? If so the get some more text... */
-
- if ( lpClient->fifoOutputStop == 0 )
- {
- /*
- * Read the bytes from the file and the convert
- * the buffer into netascii, which may double
- * the nChars.
- */
- nChars = _lread(hfFile, (LPSTR) szBuffer, iBufSize);
- if ( nChars != HFILE_ERROR )
- {
- nChars = netascii((LPSTR)szBuffer, nChars);
- if ( nChars == -1 )
- {
- lpClient->iState = STATE_FINISHED;
- fingerLog(DEBUG_OFF, IDS_REQUEST_ERR, (LPSTR) "fingerSendFile");
- return(FALSE);
- }
- }
-
- lpClient->fifoOutputStop = nChars;
- lpClient->fifoOutputStart = nChars;
-
- if ( nChars == HFILE_ERROR )
- {
- lpClient->iState = STATE_FINISHED;
- fingerLog(DEBUG_OFF, IDS_FILE_ERR);
- return(FALSE);
- }
- } else { nChars = lpClient->fifoOutputStop; }
-
- /* OK, send the stuff in the buffer to the client */
-
- fifoStart = lpClient->fifoOutputStart - nChars;
- if (nChars > 0) // Cannot send 0 bytes - WSAEINVAL
- nBytesSent = send(sSocket, (LPSTR) &szBuffer[fifoStart], nChars, 0);
- else nBytesSent = 0;
-
- /*
- * Oh no! A Winsock error occured!
- *
- * WSAEWOULDBLOCK - Means we should wait until a new FD_READ
- * is posted, so don't panic.
- */
-
- if ( nBytesSent == SOCKET_ERROR )
- {
- lpClient->iExtErr = WSAGetLastError();
- lpClient->iState = STATE_SENDING;
-
- if ( lpClient->iExtErr == WSAEWOULDBLOCK )
- {
- #ifndef NDEBUG
- // OkMsgBox("clientSendFile", "Socket Error: WSAEWOULDBLOCK (%d)", nChars);
- #endif
- return(TRUE); // OK, we'll wait for FD_READ
- } else {
- lpClient->iState = STATE_WSERROR;
- DisplayWSError("Sending");
- return(FALSE);
- }
-
- } else {
- UpdateDisplay((LPSTR) &szBuffer[fifoStart], nBytesSent);
- lpClient->fifoOutputStop -= nBytesSent;
- }
-
- /* Finished sending info, now send .plan */
- if ((lpClient->fifoOutputStop == 0) && (lpClient->iState == STATE_SEND_TIME))
- {
- if (hfFile == HFILE_ERROR)
- {
- nChars = 0;
- nBytesSent = 0;
- lpClient->iState = STATE_FINISHED;
- } else
- lpClient->iState = STATE_SENDING;
- }
-
-
- /* Reached EOF and sent all of the bytes? */
-
- if ( ( nChars == 0 ) && ( nChars == nBytesSent ) )
- {
- /*
- * These must come BEFORE the call to OkMsgBox
- * since this will cause the program to yeild
- * and more FD_WRITE messages will get
- * posted.
- */
- lpClient->iState = STATE_FINISHED;
- lpClient->iExtErr = 0;
- #ifndef NDEBUG
- // OkMsgBox("clientSendFile", "Finger is complete.");
- #endif
- FingerFinished();
- }
-
- } while ( lpClient->iState == STATE_SENDING );
-
- return(FALSE);
- }
-
-
- // Server function
-
- BOOL fingerServer(LPCLIENT lpClient)
-
- // Summary ----------------------------------------------------------------
- //
- // This is the "guts" of the text server. It will get the user that
- // the client wishes to finger. If there is no user then will
- // return the default file.
- //
- // Parameters
- //
- // lpClient The client that is going to be served.
- //
- // Return
- //
- // BOOL Returns TRUE if error and client should be destroyed
- //
- // Ends -------------------------------------------------------------------
-
- {
- int nChars;
- int iErr;
- int nLen;
- int fifoStart;
- BOOL bSnarking;
- SOCKET sSocket;
- LPSTR szFile = NULL;
- LPSTR str1 = NULL;
- LPSTR str2 = NULL;
- OFSTRUCT ofOpenBuff;
- HGLOBAL hInput;
- HGLOBAL hTempFile;
- LPSTR lpInput = NULL;
- LPSTR lpTempFile = NULL;
-
-
- // Perform a sanity check
- if (lpClient == NULL) return(FALSE);
-
- // Make things easier
- szFile = lpClient->lpInputBuffer;
- fifoStart = lpClient->fifoInputStart;
- sSocket = lpClient->sSocket;
-
- // Get the request
- nChars = recv(sSocket, &szFile[fifoStart], (lpClient->iInputSize - fifoStart), 0);
-
- if ( nChars == SOCKET_ERROR )
- {
- lpClient->iExtErr = WSAGetLastError();
- if ( lpClient->iExtErr != WSAEWOULDBLOCK )
- {
- lpClient->iState = STATE_WSERROR;
- return(TRUE);
- }
- else szFile[fifoStart] = '\0';
- }
- fifoStart += nChars;
-
- /* Did we get everything yet? <CRLF> */
- if ( (str2 = lstrchr(szFile, '\n')) != NULL )
- *str2 = '\0';
- if ( (str1 = lstrchr(szFile, '\r')) != NULL )
- *str1 = '\0';
-
- szFile = RemoveIAC(szFile);
-
- /*
- * Now, have we already started processing request?
- */
- if ( lpClient->iState != STATE_WAIT_FOR_USER ) return(FALSE);
-
- // OK, we have gotten the request...
- if ( ( str1 != NULL ) && ( str2 != NULL ) )
- {
- fingerLog(DEBUG_HIGH, IDS_RECV_S, (LPSTR)szFile, sSocket);
-
- if ( lpClient->hfFile == HFILE_ERROR)
- {
- if ( ( lstrlen(szFile) == 0) || ( bOnlySnark ) )
- {
- bSnarking = TRUE;
- lpClient->hfFile = OpenFile(szLocalFile, &ofOpenBuff, OF_SHARE_DENY_WRITE);
- if ( lpClient->hfFile == HFILE_ERROR )
- lpClient->iState = STATE_FINISHED;
- else
- lpClient->iState = STATE_SENDING;
- } else if ( !IllegalRequest(szFile) )
- {
- bSnarking = FALSE;
- hInput = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, MAX_PATH);
- if ( hInput == NULL ) return(TRUE);
-
- /* Now get a pointer to it */
- lpInput = GlobalLock(hInput);
- if (lpInput == NULL )
- {
- GlobalFree(hInput);
- return(TRUE);
- }
-
- hTempFile = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, MAX_FNAME);
- if ( hTempFile == NULL )
- {
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- return(TRUE);
- }
-
- /* Now get a pointer to it */
- lpTempFile = GlobalLock(hTempFile);
- if (lpTempFile == NULL )
- {
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- GlobalFree(hTempFile);
- return(TRUE);
- }
-
- lstrcpy(lpInput, (LPSTR)szFileDir);
- lstrcat(lpInput, "\\");
-
- if ( ( lstrlen(szFile) + lstrlen(lpInput) + 14 ) < MAX_PATH )
- {
- lstrcat(lpInput, szFile);
- lstrcat(lpInput, "\\USERINFO.INI");
-
- lpClient->hfFile = OpenFile(lpInput, &ofOpenBuff, OF_EXIST);
-
- if ( lpClient->hfFile != HFILE_ERROR )
- {
- GetPrivateProfileString( "FingerInfo"
- , "Plan"
- , "FINGER"
- , lpTempFile
- , MAX_FNAME
- , (LPSTR) lpInput );
-
- if (IllegalRequest(lpTempFile))
- {
- lstrcpy(lpTempFile, "FINGER");
- }
-
- lstrcpy(lpInput, (LPSTR)szFileDir);
- lstrcat(lpInput, "\\");
- lstrcat(lpInput, szFile);
- lstrcat(lpInput, "\\");
- lstrcat(lpInput, lpTempFile);
-
- lpClient->hfFile = OpenFile(lpInput, &ofOpenBuff, OF_SHARE_DENY_WRITE);
- lstrcpy(szFile, lpInput);
- fifoStart = lstrlen(szFile);
- lpClient->iState = STATE_SEND_TIME;
- } else {
- lpClient->iState = STATE_FINISHED;
- }
- } else {
- fingerLog(DEBUG_OFF, IDS_REQUEST_ERR, (LPSTR)"fingerServer");
- }
-
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- GlobalUnlock(hTempFile);
- GlobalFree(hTempFile);
- }
-
- /* There is no matching user */
- }
- lpClient->fifoInputStart = fifoStart;
-
- } else { // We have not gotten the complete request yet...
- lpClient->fifoInputStart = fifoStart;
- }
-
- if ( lpClient->iState == STATE_FINISHED ) return(TRUE);
- else return(FALSE);
- }
-