⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.c

📁 ipp打印机服务器原代码 注意:请将ipp.gz改为ipp.tar.gz 然后使用tar zxvf ipp.tar.gz解压 站长注意
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * "$Id: client.c,v 1.197 2005/01/03 19:29:59 mike Exp $" * *   Client routines for the Common UNIX Printing System (CUPS) scheduler. * *   Copyright 1997-2005 by Easy Software Products, all rights reserved. * *   These coded instructions, statements, and computer programs are the *   property of Easy Software Products and are protected by Federal *   copyright law.  Distribution and use rights are outlined in the file *   "LICENSE.txt" which should have been included with this file.  If this *   file is missing or damaged please contact Easy Software Products *   at: * *       Attn: CUPS Licensing Information *       Easy Software Products *       44141 Airport View Drive, Suite 204 *       Hollywood, Maryland 20636 USA * *       Voice: (301) 373-9600 *       EMail: cups-info@cups.org *         WWW: http://www.cups.org * * Contents: * *   AcceptClient()        - Accept a new client. *   CloseAllClients()     - Close all remote clients immediately. *   CloseClient()         - Close a remote client. *   EncryptClient()       - Enable encryption for the client... *   IsCGI()               - Is the resource a CGI script/program? *   ReadClient()          - Read data from a client. *   SendCommand()         - Send output from a command via HTTP. *   SendError()           - Send an error message via HTTP. *   SendFile()            - Send a file via HTTP. *   SendHeader()          - Send an HTTP request. *   UpdateCGI()           - Read status messages from CGI scripts and programs. *   WriteClient()         - Write data to a client as needed. *   check_if_modified()   - Decode an "If-Modified-Since" line. *   decode_auth()         - Decode an authorization string. *   get_file()            - Get a filename and state info. *   install_conf_file()   - Install a configuration file. *   is_path_absolute()    - Is a path absolute and free of relative elements. *   pipe_command()        - Pipe the output of a command to the remote client. *   CDSAReadFunc()        - Read function for CDSA decryption code. *   CDSAWriteFunc()       - Write function for CDSA encryption code. *//* * Include necessary headers... */#if	0#include <cups/http-private.h>#endif#include "cupsd.h"#include <grp.h>/* * Local functions... */#if	0static int		check_if_modified(client_t *con,			                  struct stat *filestats);static void		decode_auth(client_t *con);static char		*get_file(client_t *con, struct stat *filestats, 			          char *filename, int len);static http_status_t	install_conf_file(client_t *con);static int		is_path_absolute(const char *path);static int		pipe_command(client_t *con, int infile, int *outfile,			             char *command, char *options);#ifdef HAVE_CDSASSLstatic OSStatus		CDSAReadFunc(SSLConnectionRef connection, void *data,			             size_t *dataLength);static OSStatus		CDSAWriteFunc(SSLConnectionRef connection,			              const void *data, size_t *dataLength);#endif /* HAVE_CDSASSL */#endifint	SFD = -1;static int printer_get(client_t* con, char* dev);/* * 'AcceptClient()' - Accept a new client. */voidAcceptClient(listener_t *lis)	/* I - Listener socket */{  int			i;	/* Looping var */  int			count;	/* Count of connections on a host */  int			val;	/* Parameter value */  client_t		*con;	/* New client pointer */  unsigned		address;/* Address of client */  struct hostent	*host;	/* Host entry for address */  static time_t		last_dos = 0;				/* Time of last DoS attack */  DEBUG_printf(("\nFunction AcceptClient()  START...... \n"));   LogMessage(L_DEBUG2, "AcceptClient(lis=%p) %d NumClients = %d",             lis, lis->fd, NumClients); /*  * Make sure we don't have a full set of clients already...  */  if (NumClients == MaxClients)    return; /*  * Get a pointer to the next available client...  */  con = Clients + NumClients;  memset(con, 0, sizeof(client_t));  con->http.activity = time(NULL);  con->file          = -1; /*  * Accept the client and get the remote address...  */  val = sizeof(struct sockaddr_in);  if ((con->http.fd = accept(lis->fd, (struct sockaddr *)&(con->http.hostaddr),                             &val)) < 0)  {    DEBUG_printf(("Unable to accept client connection - %s.",               strerror(errno)));    LogMessage(L_ERROR, "Unable to accept client connection - %s.",               strerror(errno));    return;  }  con->http.hostaddr.sin_port = lis->address.sin_port; /*  * Check the number of clients on the same address...  */  for (i = 0, count = 0; i < NumClients; i ++)    if (memcmp(&(Clients[i].http.hostaddr), &(con->http.hostaddr),               sizeof(con->http.hostaddr)) == 0)    {      count ++;      if (count >= MaxClientsPerHost)        break;    }  if (count >= MaxClientsPerHost)  {    if ((time(NULL) - last_dos) >= 60)    {      last_dos = time(NULL);      LogMessage(L_WARN, "Possible DoS attack - more than %d clients connecting from %s!",        	 MaxClientsPerHost, Clients[i].http.hostname);    }#ifdef WIN32    closesocket(con->http.fd);#else    close(con->http.fd);#endif /* WIN32 */    return;  } /*  * Get the hostname or format the IP address as needed...  */  address = ntohl(con->http.hostaddr.sin_addr.s_addr);  if (HostNameLookups)#ifndef __sgi    host = gethostbyaddr((char *)&(con->http.hostaddr.sin_addr),                         sizeof(struct in_addr), AF_INET);#else    host = gethostbyaddr(&(con->http.hostaddr.sin_addr),                         sizeof(struct in_addr), AF_INET);#endif /* !__sgi */  else    host = NULL;  if (address == 0x7f000001)  {   /*    * Map accesses from the loopback interface to "localhost"...    */    strlcpy(con->http.hostname, "localhost", sizeof(con->http.hostname));  }  else if (con->http.hostaddr.sin_addr.s_addr == ServerAddr.sin_addr.s_addr)  {   /*    * Map accesses from the same host to the server name.    */    strlcpy(con->http.hostname, ServerName, sizeof(con->http.hostname));  }  else if (host == NULL)  {    sprintf(con->http.hostname, "%d.%d.%d.%d", (address >> 24) & 255,            (address >> 16) & 255, (address >> 8) & 255, address & 255);    if (HostNameLookups == 2)    {     /*      * Can't have an unresolved IP address with double-lookups enabled...      */#ifdef WIN32      closesocket(con->http.fd);#else      close(con->http.fd);#endif /* WIN32 */      LogMessage(L_WARN, "Name lookup failed - connection from %s closed!",                 con->http.hostname);      return;    }  }  else    strlcpy(con->http.hostname, host->h_name, sizeof(con->http.hostname));  if (HostNameLookups == 2)  {   /*    * Do double lookups as needed...    */    if ((host = httpGetHostByName(con->http.hostname)) != NULL)    {     /*      * See if the hostname maps to the IP address...      */      if (host->h_length != 4 || host->h_addrtype != AF_INET)      {       /*        * Not an IPv4 address...	*/	host = NULL;      }      else      {       /*        * Compare all of the addresses against this one...	*/	for (i = 0; host->h_addr_list[i]; i ++)          if (memcmp(&(con->http.hostaddr.sin_addr), host->h_addr_list[i], 4) == 0)	    break;        if (!host->h_addr_list[i])	  host = NULL;      }    }    if (host == NULL)    {     /*      * Can't have a hostname that doesn't resolve to the same IP address      * with double-lookups enabled...      */#ifdef WIN32      closesocket(con->http.fd);#else      close(con->http.fd);#endif /* WIN32 */      LogMessage(L_WARN, "IP lookup failed - connection from %s closed!",                 con->http.hostname);      return;    }  }  LogMessage(L_DEBUG, "AcceptClient: %d from %s:%d.", con->http.fd,             con->http.hostname, ntohs(con->http.hostaddr.sin_port)); /*  * Using TCP_NODELAY improves responsiveness, especially on systems  * with a slow loopback interface...  Since we write large buffers  * when sending print files and requests, there shouldn't be any  * performance penalty for this...  */  val = 1;  setsockopt(con->http.fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));  /*  * Close this file on all execs...  */  fcntl(con->http.fd, F_SETFD, fcntl(con->http.fd, F_GETFD) | FD_CLOEXEC); /*  * Add the socket to the select() input mask.  */  LogMessage(L_DEBUG2, "AcceptClient: Adding fd %d to InputSet...",             con->http.fd);  FD_SET(con->http.fd, InputSet);  NumClients ++; /*  * Temporarily suspend accept()'s until we lose a client...  */  if (NumClients == MaxClients)    PauseListening();#if	0#ifdef HAVE_SSL /*  * See if we are connecting on a secure port...  */  if (lis->encryption == HTTP_ENCRYPT_ALWAYS)  {   /*    * https connection; go secure...    */    con->http.encryption = HTTP_ENCRYPT_ALWAYS;    EncryptClient(con);  }#endif /* HAVE_SSL */#endif  DEBUG_printf(("Function AcceptClient()\n\n")); }/* * 'CloseAllClients()' - Close all remote clients immediately. */voidCloseAllClients(void){  while (NumClients > 0)    CloseClient(Clients);}/* * 'CloseClient()' - Close a remote client. */int				/* O - 1 if partial close, 0 if fully closed */CloseClient(client_t *con)	/* I - Client to close */{  int		partial;	/* Do partial close for SSL? */#if defined(HAVE_LIBSSL)  SSL_CTX	*context;	/* Context for encryption */  SSL		*conn;		/* Connection for encryption */  unsigned long	error;		/* Error code */#elif defined(HAVE_GNUTLS)  http_tls_t     *conn;		/* TLS connection information */  int            error;		/* Error code */  gnutls_certificate_server_credentials *credentials;				/* TLS credentials */#endif /* HAVE_GNUTLS */  LogMessage(L_DEBUG, "CloseClient: %d", con->http.fd);  partial = 0;#if	0#ifdef HAVE_SSL /*  * Shutdown encryption as needed...  */  if (con->http.tls)  {    partial = 1;#  ifdef HAVE_LIBSSL    conn    = (SSL *)(con->http.tls);    context = SSL_get_SSL_CTX(conn);    switch (SSL_shutdown(conn))    {      case 1 :          LogMessage(L_INFO, "CloseClient: SSL shutdown successful!");	  break;      case -1 :          LogMessage(L_ERROR, "CloseClient: Fatal error during SSL shutdown!");      default :	  while ((error = ERR_get_error()) != 0)	    LogMessage(L_ERROR, "CloseClient: %s", ERR_error_string(error, NULL));          break;    }    SSL_CTX_free(context);    SSL_free(conn);#  elif defined(HAVE_GNUTLS)    conn        = (http_tls_t *)(con->http.tls);    credentials = (gnutls_certificate_server_credentials *)(conn->credentials);    error = gnutls_bye(conn->session, GNUTLS_SHUT_WR);    switch (error)    {      case GNUTLS_E_SUCCESS:	LogMessage(L_INFO, "CloseClient: SSL shutdown successful!");	break;      default:	LogMessage(L_ERROR, "CloseClient: %s", gnutls_strerror(error));	break;    }    gnutls_deinit(conn->session);    gnutls_certificate_free_credentials(*credentials);    free(credentials);    free(conn);#  elif defined(HAVE_CDSASSL)    status = SSLClose((SSLContextRef)con->http.tls);    SSLDisposeContext((SSLContextRef)con->http.tls);#  endif /* HAVE_LIBSSL */    con->http.tls = NULL;  }#endif /* HAVE_SSL */#endif /*  * Close the socket and clear the file from the input set for select()...  */  if (con->http.fd > 0)  {    if (partial)    {     /*      * Only do a partial close so that the encrypted client gets everything.      */      LogMessage(L_DEBUG2, "CloseClient: Removing fd %d from OutputSet...",        	 con->http.fd);      shutdown(con->http.fd, 0);      FD_CLR(con->http.fd, OutputSet);    }    else    {     /*      * Shut the socket down fully...      */      LogMessage(L_DEBUG2, "CloseClient: Removing fd %d from InputSet and OutputSet...",        	 con->http.fd);      close(con->http.fd);      FD_CLR(con->http.fd, InputSet);      FD_CLR(con->http.fd, OutputSet);      con->http.fd = 0;    }  }  if (con->pipe_pid != 0)  {   /*    * Stop any CGI process...    */    LogMessage(L_DEBUG2, "CloseClient: %d Killing process ID %d...",               con->http.fd, con->pipe_pid);    kill(con->pipe_pid, SIGKILL);  }  if (con->file >= 0)  {    if (FD_ISSET(con->file, InputSet))    {      LogMessage(L_DEBUG2, "CloseClient: %d Removing fd %d from InputSet...",        	 con->http.fd, con->file);      FD_CLR(con->file, InputSet);    }    LogMessage(L_DEBUG2, "CloseClient: %d Closing data file %d.",               con->http.fd, con->file);    close(con->file);    con->file = -1;  }  if (!partial)  {   /*    * Free memory...    */    if (con->http.input_set)      free(con->http.input_set);    httpClearCookie(HTTP(con));    ClearString(&con->filename);    ClearString(&con->command);    ClearString(&con->options);    if (con->request)    {      ippDelete(con->request);      con->request = NULL;    }    if (con->response)    {      ippDelete(con->response);      con->response = NULL;    }    if (con->language)    {      cupsLangFree(con->language);      con->language = NULL;    }   /*    * Re-enable new client connections if we are going back under the

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -