Ejemplo n.º 1
0
http_status_t				/* O - HTTP status */
cupsPutFd(http_t     *http,		/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
          const char *resource,		/* I - Resource name */
	  int        fd)		/* I - File descriptor */
{
  ssize_t	bytes;			/* Number of bytes read */
  int		retries;		/* Number of retries */
  char		buffer[8192];		/* Buffer for file */
  http_status_t	status;			/* HTTP status from server */
  int		new_auth = 0;		/* Using new auth information? */
  int		digest;			/* Are we using Digest authentication? */


 /*
  * Range check input...
  */

  DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", (void *)http, resource, fd));

  if (!resource || fd < 0)
  {
    if (http)
      http->error = EINVAL;

    return (HTTP_STATUS_ERROR);
  }

  if (!http)
    if ((http = _cupsConnect()) == NULL)
      return (HTTP_STATUS_SERVICE_UNAVAILABLE);

 /*
  * Then send PUT requests to the HTTP server...
  */

  retries = 0;

  do
  {
    if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
    {
      httpClearFields(http);
      if (httpReconnect2(http, 30000, NULL))
      {
	status = HTTP_STATUS_ERROR;
	break;
      }
    }

    DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
                  http->authstring));

    httpClearFields(http);
    httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
    httpSetExpect(http, HTTP_STATUS_CONTINUE);

    digest = http->authstring && !strncmp(http->authstring, "Digest ", 7);

    if (digest && !new_auth)
    {
     /*
      * Update the Digest authentication string...
      */

      _httpSetDigestAuthString(http, http->nextnonce, "PUT", resource);
    }

#ifdef HAVE_GSSAPI
    if (http->authstring && !strncmp(http->authstring, "Negotiate", 9) && !new_auth)
    {
     /*
      * Do not use cached Kerberos credentials since they will look like a
      * "replay" attack...
      */

      _cupsSetNegotiateAuthString(http, "PUT", resource);
    }
#endif /* HAVE_GSSAPI */

    httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);

    if (httpPut(http, resource))
    {
      if (httpReconnect2(http, 30000, NULL))
      {
        status = HTTP_STATUS_ERROR;
	break;
      }
      else
      {
        status = HTTP_STATUS_UNAUTHORIZED;
        continue;
      }
    }

   /*
    * Wait up to 1 second for a 100-continue response...
    */

    if (httpWait(http, 1000))
      status = httpUpdate(http);
    else
      status = HTTP_STATUS_CONTINUE;

    if (status == HTTP_STATUS_CONTINUE)
    {
     /*
      * Copy the file...
      */

      lseek(fd, 0, SEEK_SET);

      while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
	if (httpCheck(http))
	{
          if ((status = httpUpdate(http)) != HTTP_STATUS_CONTINUE)
            break;
	}
	else
          httpWrite2(http, buffer, (size_t)bytes);
    }

    if (status == HTTP_STATUS_CONTINUE)
    {
      httpWrite2(http, buffer, 0);

      while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
    }

    if (status == HTTP_STATUS_ERROR && !retries)
    {
      DEBUG_printf(("2cupsPutFd: retry on status %d", status));

      retries ++;

      /* Flush any error message... */
      httpFlush(http);

      /* Reconnect... */
      if (httpReconnect2(http, 30000, NULL))
      {
        status = HTTP_STATUS_ERROR;
        break;
      }

      /* Try again... */
      continue;
    }

    DEBUG_printf(("2cupsPutFd: status=%d", status));

    new_auth = 0;

    if (status == HTTP_STATUS_UNAUTHORIZED)
    {
     /*
      * Flush any error message...
      */

      httpFlush(http);

     /*
      * See if we can do authentication...
      */

      new_auth = 1;

      if (cupsDoAuthentication(http, "PUT", resource))
      {
        status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
        break;
      }

      if (httpReconnect2(http, 30000, NULL))
      {
        status = HTTP_STATUS_ERROR;
        break;
      }

      continue;
    }
#ifdef HAVE_SSL
    else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
    {
      /* Flush any error message... */
      httpFlush(http);

      /* Reconnect... */
      if (httpReconnect2(http, 30000, NULL))
      {
        status = HTTP_STATUS_ERROR;
        break;
      }

      /* Upgrade with encryption... */
      httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);

      /* Try again, this time with encryption enabled... */
      continue;
    }
#endif /* HAVE_SSL */
  }
  while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED ||
         (status == HTTP_STATUS_ERROR && retries < 2));

 /*
  * See if we actually put the file or an error...
  */

  if (status != HTTP_STATUS_CREATED)
  {
    _cupsSetHTTPError(status);
    httpFlush(http);
  }

  DEBUG_printf(("1cupsPutFd: Returning %d...", status));

  return (status);
}
Ejemplo n.º 2
0
http_status_t				/* O - HTTP status */
cupsGetFd(http_t     *http,		/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
	  const char *resource,		/* I - Resource name */
	  int        fd)		/* I - File descriptor */
{
  ssize_t	bytes;			/* Number of bytes read */
  char		buffer[8192];		/* Buffer for file */
  http_status_t	status;			/* HTTP status from server */
  char		if_modified_since[HTTP_MAX_VALUE];
					/* If-Modified-Since header */
  int		new_auth = 0;		/* Using new auth information? */
  int		digest;			/* Are we using Digest authentication? */


 /*
  * Range check input...
  */

  DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", (void *)http, resource, fd));

  if (!resource || fd < 0)
  {
    if (http)
      http->error = EINVAL;

    return (HTTP_STATUS_ERROR);
  }

  if (!http)
    if ((http = _cupsConnect()) == NULL)
      return (HTTP_STATUS_SERVICE_UNAVAILABLE);

 /*
  * Then send GET requests to the HTTP server...
  */

  strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
          sizeof(if_modified_since));

  do
  {
    if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
    {
      httpClearFields(http);
      if (httpReconnect2(http, 30000, NULL))
      {
	status = HTTP_STATUS_ERROR;
	break;
      }
    }

    httpClearFields(http);
    httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);

    digest = http->authstring && !strncmp(http->authstring, "Digest ", 7);

    if (digest && !new_auth)
    {
     /*
      * Update the Digest authentication string...
      */

      _httpSetDigestAuthString(http, http->nextnonce, "GET", resource);
    }

#ifdef HAVE_GSSAPI
    if (http->authstring && !strncmp(http->authstring, "Negotiate", 9) && !new_auth)
    {
     /*
      * Do not use cached Kerberos credentials since they will look like a
      * "replay" attack...
      */

      _cupsSetNegotiateAuthString(http, "GET", resource);
    }
#endif /* HAVE_GSSAPI */

    httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);

    if (httpGet(http, resource))
    {
      if (httpReconnect2(http, 30000, NULL))
      {
        status = HTTP_STATUS_ERROR;
	break;
      }
      else
      {
        status = HTTP_STATUS_UNAUTHORIZED;
        continue;
      }
    }

    new_auth = 0;

    while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);

    if (status == HTTP_STATUS_UNAUTHORIZED)
    {
     /*
      * Flush any error message...
      */

      httpFlush(http);

     /*
      * See if we can do authentication...
      */

      new_auth = 1;

      if (cupsDoAuthentication(http, "GET", resource))
      {
        status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
        break;
      }

      if (httpReconnect2(http, 30000, NULL))
      {
        status = HTTP_STATUS_ERROR;
        break;
      }

      continue;
    }
#ifdef HAVE_SSL
    else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
    {
      /* Flush any error message... */
      httpFlush(http);

      /* Reconnect... */
      if (httpReconnect2(http, 30000, NULL))
      {
        status = HTTP_STATUS_ERROR;
        break;
      }

      /* Upgrade with encryption... */
      httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);

      /* Try again, this time with encryption enabled... */
      continue;
    }
#endif /* HAVE_SSL */
  }
  while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED);

 /*
  * See if we actually got the file or an error...
  */

  if (status == HTTP_STATUS_OK)
  {
   /*
    * Yes, copy the file...
    */

    while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
      write(fd, buffer, (size_t)bytes);
  }
  else
  {
    _cupsSetHTTPError(status);
    httpFlush(http);
  }

 /*
  * Return the request status...
  */

  DEBUG_printf(("1cupsGetFd: Returning %d...", status));

  return (status);
}
Ejemplo n.º 3
0
char *					/* O - Pathname or NULL */
file_find(const char *path,		/* I - Path "dir;dir;dir" */
          const char *s)		/* I - File to find */
{
  int		i;			/* Looping var */
  int		retry;			/* Current retry */
  char		*temp,			/* Current position in filename */
		method[HTTP_MAX_URI],	/* Method/scheme */
		username[HTTP_MAX_URI],	/* Username:password */
		hostname[HTTP_MAX_URI],	/* Hostname */
		resource[HTTP_MAX_URI];	/* Resource */
  int		port;			/* Port number */
  const char	*connhost;		/* Host to connect to */
  int		connport;		/* Port to connect to */
  char		connpath[HTTP_MAX_URI],	/* Path for GET */
		connauth[HTTP_MAX_VALUE];/* Auth string */
  http_status_t	status;			/* Status of request... */
  FILE		*fp;			/* Web file */
  int		bytes,			/* Bytes read */
		count,			/* Number of bytes so far */
		total;			/* Total bytes in file */
  static char	filename[HTTP_MAX_URI];	/* Current filename */


 /*
  * If the filename is NULL, return NULL...
  */

  if (s == NULL)
    return (NULL);

  if (strncmp(s, "http:", 5) == 0 ||
      (path != NULL && strncmp(path, "http:", 5) == 0))
    strcpy(method, "http");
#ifdef HAVE_LIBSSL
  else if (strncmp(s, "https:", 6) == 0 ||
           (path != NULL && strncmp(path, "https:", 6) == 0))
    strcpy(method, "https");
#endif /* HAVE_LIBSSL */
  else
    strcpy(method, "file");

  if (strcmp(method, "file") == 0)
  {
   /*
    * If the path is NULL or empty, return the filename...
    */

    if (path == NULL || !path[0])
      return ((char *)s);

   /*
    * Else loop through the path string until we reach the end...
    */

    while (*path != '\0')
    {
     /*
      * Copy the path directory...
      */

      temp = filename;

      while (*path != ';' && *path && temp < (filename + sizeof(filename) - 1))
	*temp++ = *path++;

      if (*path == ';')
	path ++;

     /*
      * Append a slash as needed...
      */

      if (temp > filename && temp < (filename + sizeof(filename) - 1) &&
          s[0] != '/')
	*temp++ = '/';

     /*
      * Append the filename...
      */

      strncpy(temp, s, sizeof(filename) - (temp - filename));
      filename[sizeof(filename) - 1] = '\0';

     /*
      * See if the file exists...
      */

      if (!access(filename, 0))
	return (filename);
    }
  }
  else
  {
   /*
    * Remote file; look it up in the web cache, and then try getting it
    * from the remote system...
    */

    for (i = 0; i < web_files; i ++)
      if (web_cache[i].url && strcmp(web_cache[i].url, s) == 0)
        return (web_cache[i].name);

#ifdef HAVE_LIBSSL
    if (strncmp(s, "http:", 5) == 0 || strncmp(s, "https:", 6) == 0)
#else
    if (strncmp(s, "http:", 5) == 0)
#endif /* HAVE_LIBSSL */
      httpSeparate(s, method, username, hostname, &port, resource);
    else if (s[0] == '/')
    {
      httpSeparate(path, method, username, hostname, &port, resource);
      strcpy(resource, s);
    }
    else
    {
      if (strncmp(s, "./", 2) == 0)
        snprintf(filename, sizeof(filename), "%s/%s", path, s + 2);
      else
        snprintf(filename, sizeof(filename), "%s/%s", path, s);

      httpSeparate(filename, method, username, hostname, &port, resource);
    }

    for (status = HTTP_ERROR, retry = 0;
         status == HTTP_ERROR && retry < 5;
         retry ++)
    {
      if (proxy_port)
      {
       /*
        * Send request to proxy host...
        */

        connhost = proxy_host;
        connport = proxy_port;
        snprintf(connpath, sizeof(connpath), "%s://%s:%d%s", method,
                 hostname, port, resource);
      }
      else
      {
       /*
        * Send request to host directly...
        */

        connhost = hostname;
        connport = port;
        strcpy(connpath, resource);
      }

      if (http != NULL && strcasecmp(http->hostname, hostname) != 0)
      {
        httpClose(http);
        http = NULL;
      }

      if (http == NULL)
      {
        progress_show("Connecting to %s...", connhost);
        atexit(file_cleanup);

#ifdef HAVE_LIBSSL
        if (strcmp(method, "http") == 0)
          http = httpConnect(connhost, connport);
	else
          http = httpConnectEncrypt(connhost, connport, HTTP_ENCRYPT_ALWAYS);
#else
        http = httpConnect(connhost, connport);
#endif /* HAVE_LIBSSL */

        if (http == NULL)
	{
          progress_hide();
          progress_error("Unable to connect to %s!", connhost);
          return (NULL);
        }
      }

      progress_show("Getting %s...", connpath);

      httpClearFields(http);
      httpSetField(http, HTTP_FIELD_HOST, hostname);
      httpSetField(http, HTTP_FIELD_USER_AGENT, "HTMLDOC v" SVERSION);
      httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive");

      if (username[0])
      {
        strcpy(connauth, "Basic ");
        httpEncode64(connauth + 6, username);
        httpSetField(http, HTTP_FIELD_AUTHORIZATION, connauth);
      }

      if (!httpGet(http, connpath))
	while ((status = httpUpdate(http)) == HTTP_CONTINUE);
      else
	status = HTTP_ERROR;

      if (status >= HTTP_MOVED_PERMANENTLY && status <= HTTP_SEE_OTHER)
      {
       /*
        * Flush text...
	*/

	httpFlush(http);

       /*
        * Grab new location from HTTP data...
	*/

        httpSeparate(httpGetField(http, HTTP_FIELD_LOCATION), method, username,
	             hostname, &port, resource);
        status = HTTP_ERROR;
      }
    }

    if (status != HTTP_OK)
    {
      progress_hide();
      progress_error("HTTP error %d: %s!", status, httpStatus(status));
      httpFlush(http);
      return (NULL);
    }

    if ((fp = file_temp(filename, sizeof(filename))) == NULL)
    {
      progress_hide();
      progress_error("Unable to create temporary file \"%s\": %s", filename,
                     strerror(errno));
      httpFlush(http);
      return (NULL);
    }

    if ((total = atoi(httpGetField(http, HTTP_FIELD_CONTENT_LENGTH))) == 0)
      total = 8192;

    count = 0;
    while ((bytes = httpRead(http, resource, sizeof(resource))) > 0)
    {
      count += bytes;
      progress_update((100 * count / total) % 101);
      fwrite(resource, 1, bytes, fp);
    }

    progress_hide();

    fclose(fp);

    web_cache[web_files - 1].name = strdup(filename);
    web_cache[web_files - 1].url  = strdup(s);

    return (filename);
  }

  return (NULL);
}
Ejemplo n.º 4
0
http_status_t				/* O - HTTP status */
cupsGetFd(http_t     *http,		/* I - HTTP connection to server */
	  const char *resource,		/* I - Resource name */
	  int        fd)		/* I - File descriptor */
{
  int		bytes;			/* Number of bytes read */
  char		buffer[8192];		/* Buffer for file */
  http_status_t	status;			/* HTTP status from server */
  char		if_modified_since[HTTP_MAX_VALUE];
					/* If-Modified-Since header */


 /*
  * Range check input...
  */

  DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)\n", http,
                resource, fd));

  if (!http || !resource || fd < 0)
  {
    if (http)
      http->error = EINVAL;

    return (HTTP_ERROR);
  }

 /*
  * Then send GET requests to the HTTP server...
  */

  strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
          sizeof(if_modified_since));

  do
  {
    httpClearFields(http);
    httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
    httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);

    if (httpGet(http, resource))
    {
      if (httpReconnect(http))
      {
        status = HTTP_ERROR;
	break;
      }
      else
      {
        status = HTTP_UNAUTHORIZED;
        continue;
      }
    }

    while ((status = httpUpdate(http)) == HTTP_CONTINUE);

    if (status == HTTP_UNAUTHORIZED)
    {
     /*
      * Flush any error message...
      */

      httpFlush(http);

     /*
      * See if we can do authentication...
      */

      if (cupsDoAuthentication(http, "GET", resource))
        break;

      if (httpReconnect(http))
      {
        status = HTTP_ERROR;
        break;
      }

      continue;
    }
#ifdef HAVE_SSL
    else if (status == HTTP_UPGRADE_REQUIRED)
    {
      /* Flush any error message... */
      httpFlush(http);

      /* Reconnect... */
      if (httpReconnect(http))
      {
        status = HTTP_ERROR;
        break;
      }

      /* Upgrade with encryption... */
      httpEncryption(http, HTTP_ENCRYPT_REQUIRED);

      /* Try again, this time with encryption enabled... */
      continue;
    }
#endif /* HAVE_SSL */
  }
  while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);

 /*
  * See if we actually got the file or an error...
  */

  if (status == HTTP_OK)
  {
   /*
    * Yes, copy the file...
    */

    while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
      write(fd, buffer, bytes);
  }
  else
  {
    _cupsSetHTTPError(status);
    httpFlush(http);
  }

 /*
  * Return the request status...
  */

  return (status);
}
Ejemplo n.º 5
0
int					/* O - 0 on success, -1 on error */
cupsDoAuthentication(
    http_t     *http,			/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
    const char *method,			/* I - Request method ("GET", "POST", "PUT") */
    const char *resource)		/* I - Resource path */
{
    const char	*password,		/* Password string */
           *www_auth;		/* WWW-Authenticate header */
    char		prompt[1024],		/* Prompt for user */
                realm[HTTP_MAX_VALUE],	/* realm="xyz" string */
                nonce[HTTP_MAX_VALUE];	/* nonce="xyz" string */
    int		localauth;		/* Local authentication result */
    _cups_globals_t *cg;			/* Global data */


    DEBUG_printf(("cupsDoAuthentication(http=%p, method=\"%s\", resource=\"%s\")",
                  http, method, resource));

    if (!http)
        http = _cupsConnect();

    if (!http || !method || !resource)
        return (-1);

    DEBUG_printf(("2cupsDoAuthentication: digest_tries=%d, userpass=\"%s\"",
                  http->digest_tries, http->userpass));
    DEBUG_printf(("2cupsDoAuthentication: WWW-Authenticate=\"%s\"",
                  httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE)));

    /*
     * Clear the current authentication string...
     */

    httpSetAuthString(http, NULL, NULL);

    /*
     * See if we can do local authentication...
     */

    if (http->digest_tries < 3)
    {
        if ((localauth = cups_local_auth(http)) == 0)
        {
            DEBUG_printf(("2cupsDoAuthentication: authstring=\"%s\"",
                          http->authstring));

            if (http->status == HTTP_STATUS_UNAUTHORIZED)
                http->digest_tries ++;

            return (0);
        }
        else if (localauth == -1)
        {
            http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
            return (-1);			/* Error or canceled */
        }
    }

    /*
     * Nope, see if we should retry the current username:password...
     */

    www_auth = http->fields[HTTP_FIELD_WWW_AUTHENTICATE];

    if ((http->digest_tries > 1 || !http->userpass[0]) &&
            (!_cups_strncasecmp(www_auth, "Basic", 5) ||
             !_cups_strncasecmp(www_auth, "Digest", 6)))
    {
        /*
         * Nope - get a new password from the user...
         */

        char default_username[HTTP_MAX_VALUE];
        /* Default username */

        cg = _cupsGlobals();

        if (!cg->lang_default)
            cg->lang_default = cupsLangDefault();

        if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username",
                            default_username))
            cupsSetUser(default_username);

        snprintf(prompt, sizeof(prompt),
                 _cupsLangString(cg->lang_default, _("Password for %s on %s? ")),
                 cupsUser(),
                 http->hostname[0] == '/' ? "localhost" : http->hostname);

        http->digest_tries  = _cups_strncasecmp(www_auth, "Digest", 6) != 0;
        http->userpass[0]   = '\0';

        if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL)
        {
            http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
            return (-1);
        }

        snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(),
                 password);
    }
    else if (http->status == HTTP_STATUS_UNAUTHORIZED)
        http->digest_tries ++;

    if (http->status == HTTP_STATUS_UNAUTHORIZED && http->digest_tries >= 3)
    {
        DEBUG_printf(("1cupsDoAuthentication: Too many authentication tries (%d)",
                      http->digest_tries));

        http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
        return (-1);
    }

    /*
     * Got a password; encode it for the server...
     */

#ifdef HAVE_GSSAPI
    if (!_cups_strncasecmp(www_auth, "Negotiate", 9))
    {
        /*
         * Kerberos authentication...
         */

        if (_cupsSetNegotiateAuthString(http, method, resource))
        {
            http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
            return (-1);
        }
    }
    else
#endif /* HAVE_GSSAPI */
        if (!_cups_strncasecmp(www_auth, "Basic", 5))
        {
            /*
             * Basic authentication...
             */

            char	encode[256];		/* Base64 buffer */


            httpEncode64_2(encode, sizeof(encode), http->userpass,
                           (int)strlen(http->userpass));
            httpSetAuthString(http, "Basic", encode);
        }
        else if (!_cups_strncasecmp(www_auth, "Digest", 6))
        {
            /*
             * Digest authentication...
             */

            char	encode[33],		/* MD5 buffer */
                    digest[1024];		/* Digest auth data */

            httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
            httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);

            httpMD5(cupsUser(), realm, strchr(http->userpass, ':') + 1, encode);
            httpMD5Final(nonce, method, resource, encode);
            snprintf(digest, sizeof(digest),
                     "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", "
                     "response=\"%s\"", cupsUser(), realm, nonce, resource, encode);
            httpSetAuthString(http, "Digest", digest);
        }
        else
        {
            DEBUG_printf(("1cupsDoAuthentication: Unknown auth type: \"%s\"",
                          www_auth));
            http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
            return (-1);
        }

    DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring));

    return (0);
}
Ejemplo n.º 6
0
static void 
_post_check (GtkCupsRequest *request)
{
  http_status_t http_status;

  http_status = request->last_status;

  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %s - status %i\n", G_STRFUNC, http_status));

  request->poll_state = GTK_CUPS_HTTP_READ;

  if (http_status == HTTP_CONTINUE)
    {
      goto again; 
    }
  else if (http_status == HTTP_UNAUTHORIZED)
    {
      int auth_result = -1;
      httpFlush (request->http);

      if (request->password_state == GTK_CUPS_PASSWORD_APPLIED)
        {
          request->poll_state = GTK_CUPS_HTTP_IDLE;
          request->password_state = GTK_CUPS_PASSWORD_NOT_VALID;
          request->state = GTK_CUPS_POST_AUTH;
          request->need_password = TRUE;

          return;
        }

      /* Negotiate */
      if (strncmp (httpGetField (request->http, HTTP_FIELD_WWW_AUTHENTICATE), "Negotiate", 9) == 0)
        {
          auth_result = cupsDoAuthentication (request->http, "POST", request->resource);
        }
      /* Basic, BasicDigest, Digest and PeerCred */
      else
        {
          if (request->password_state == GTK_CUPS_PASSWORD_NONE)
            {
              cups_username = request->username;
              cupsSetPasswordCB (passwordCB);

              /* This call success for PeerCred authentication */
              auth_result = cupsDoAuthentication (request->http, "POST", request->resource);

              if (auth_result != 0)
                {
                  /* move to AUTH state to let the backend 
                   * ask for a password
                   */ 
                  request->poll_state = GTK_CUPS_HTTP_IDLE;
                  request->state = GTK_CUPS_POST_AUTH;
                  request->need_password = TRUE;

                  return;
                }
            }
          else
            {
              cups_password = request->password;
              cups_username = request->username;

              auth_result = cupsDoAuthentication (request->http, "POST", request->resource);

              if (cups_password != NULL)
                return;

              if (request->password != NULL)
                {
                  memset (request->password, 0, strlen (request->password));
                  g_free (request->password);
                  request->password = NULL;
                }

              request->password_state = GTK_CUPS_PASSWORD_APPLIED;
            }
        }

      if (auth_result ||
          httpReconnect (request->http))
        {
          /* if the password has been used, reset password_state
           * so that we ask for a new one next time around
           */ 
          if (cups_password == NULL)
            request->password_state = GTK_CUPS_PASSWORD_NONE;

          request->state = GTK_CUPS_POST_DONE;
          request->poll_state = GTK_CUPS_HTTP_IDLE;
          gtk_cups_result_set_error (request->result, 
                                     GTK_CUPS_ERROR_AUTH,
                                     0,
                                     0,
                                     "Not authorized");
          return;
        }
      
      if (request->data_io != NULL)
        g_io_channel_seek_position (request->data_io, 0, G_SEEK_SET, NULL);

      request->state = GTK_CUPS_POST_CONNECT;
      request->poll_state = GTK_CUPS_HTTP_WRITE;
    }
  else if (http_status == HTTP_ERROR)
    {
      int error = httpError (request->http);
#ifdef G_OS_WIN32
      if (error != WSAENETDOWN && error != WSAENETUNREACH)
#else
      if (error != ENETDOWN && error != ENETUNREACH)	  
#endif /* G_OS_WIN32 */
        {
          request->attempts++;
          goto again;
        }
      else
        {
          request->state = GTK_CUPS_POST_DONE;
          request->poll_state = GTK_CUPS_HTTP_IDLE;
     
          gtk_cups_result_set_error (request->result,
                                     GTK_CUPS_ERROR_HTTP,
                                     http_status,
                                     error, 
                                     "Unknown HTTP error");

          return;
        }
    }
  else if (http_status == HTTP_UPGRADE_REQUIRED)
    {
      /* Flush any error message... */
      httpFlush (request->http);

      cupsSetEncryption (HTTP_ENCRYPT_REQUIRED);
      request->state = GTK_CUPS_POST_CONNECT;

      /* Reconnect... */
      httpReconnect (request->http);

      /* Upgrade with encryption... */
      httpEncryption (request->http, HTTP_ENCRYPT_REQUIRED);
 
      request->attempts++;
      goto again;
    }
  else if (http_status != HTTP_OK)
    {
      int http_errno;

      http_errno = httpError (request->http);

      if (http_errno == EPIPE)
        request->state = GTK_CUPS_POST_CONNECT;
      else
        {
          request->state = GTK_CUPS_POST_DONE;
          gtk_cups_result_set_error (request->result,
                                     GTK_CUPS_ERROR_HTTP,
                                     http_status,
                                     http_errno, 
                                     "HTTP Error in POST %s", 
                                     g_strerror (http_errno));
          request->poll_state = GTK_CUPS_HTTP_IDLE;
 
          httpFlush (request->http); 
          return;
        }

      request->poll_state = GTK_CUPS_HTTP_IDLE;
       
      httpFlush (request->http); 
      
      request->last_status = HTTP_CONTINUE;
      httpClose (request->http);
      request->http = NULL;
      return;  
    }
  else
    {
      request->state = GTK_CUPS_POST_READ_RESPONSE;
      return;
    }

 again:
  http_status = HTTP_CONTINUE;

  if (httpCheck (request->http))
    http_status = httpUpdate (request->http);

  request->last_status = http_status;
}
Ejemplo n.º 7
0
http_status_t				/* O  - HTTP status */
cupsGetPPD3(http_t     *http,		/* I  - HTTP connection or @code CUPS_HTTP_DEFAULT@ */
            const char *name,		/* I  - Destination name */
	    time_t     *modtime,	/* IO - Modification time */
	    char       *buffer,		/* I  - Filename buffer */
	    size_t     bufsize)		/* I  - Size of filename buffer */
{
  int		http_port;		/* Port number */
  char		http_hostname[HTTP_MAX_HOST];
					/* Hostname associated with connection */
  http_t	*http2;			/* Alternate HTTP connection */
  int		fd;			/* PPD file */
  char		localhost[HTTP_MAX_URI],/* Local hostname */
		hostname[HTTP_MAX_URI],	/* Hostname */
		resource[HTTP_MAX_URI];	/* Resource name */
  int		port;			/* Port number */
  http_status_t	status;			/* HTTP status from server */
  char		tempfile[1024] = "";	/* Temporary filename */
  _cups_globals_t *cg = _cupsGlobals();	/* Pointer to library globals */


 /*
  * Range check input...
  */

  DEBUG_printf(("cupsGetPPD3(http=%p, name=\"%s\", modtime=%p(%d), buffer=%p, "
                "bufsize=%d)", http, name, modtime,
		modtime ? (int)*modtime : 0, buffer, (int)bufsize));

  if (!name)
  {
    _cupsSetError(IPP_INTERNAL_ERROR, _("No printer name"), 1);
    return (HTTP_NOT_ACCEPTABLE);
  }

  if (!modtime)
  {
    _cupsSetError(IPP_INTERNAL_ERROR, _("No modification time"), 1);
    return (HTTP_NOT_ACCEPTABLE);
  }

  if (!buffer || bufsize <= 1)
  {
    _cupsSetError(IPP_INTERNAL_ERROR, _("Bad filename buffer"), 1);
    return (HTTP_NOT_ACCEPTABLE);
  }

#ifndef WIN32
 /*
  * See if the PPD file is available locally...
  */

  if (!cg->servername[0])
    cupsServer();

  if (!_cups_strcasecmp(cg->servername, "localhost"))
  {
    char	ppdname[1024];		/* PPD filename */
    struct stat	ppdinfo;		/* PPD file information */


    snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd", cg->cups_serverroot,
             name);
    if (!stat(ppdname, &ppdinfo))
    {
     /*
      * OK, the file exists, use it!
      */

      if (buffer[0])
      {
        unlink(buffer);

	if (symlink(ppdname, buffer) && errno != EEXIST)
        {
          _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);

	  return (HTTP_SERVER_ERROR);
	}
      }
      else
      {
        int		tries;		/* Number of tries */
        const char	*tmpdir;	/* TMPDIR environment variable */
	struct timeval	curtime;	/* Current time */

       /*
	* Previously we put root temporary files in the default CUPS temporary
	* directory under /var/spool/cups.  However, since the scheduler cleans
	* out temporary files there and runs independently of the user apps, we
	* don't want to use it unless specifically told to by cupsd.
	*/

	if ((tmpdir = getenv("TMPDIR")) == NULL)
#  ifdef __APPLE__
	  tmpdir = "/private/tmp";	/* /tmp is a symlink to /private/tmp */
#  else
          tmpdir = "/tmp";
#  endif /* __APPLE__ */

       /*
	* Make the temporary name using the specified directory...
	*/

	tries = 0;

	do
	{
	 /*
	  * Get the current time of day...
	  */

	  gettimeofday(&curtime, NULL);

	 /*
	  * Format a string using the hex time values...
	  */

	  snprintf(buffer, bufsize, "%s/%08lx%05lx", tmpdir,
		   (unsigned long)curtime.tv_sec,
		   (unsigned long)curtime.tv_usec);

	 /*
	  * Try to make a symlink...
	  */

	  if (!symlink(ppdname, buffer))
	    break;

	  tries ++;
	}
	while (tries < 1000);

        if (tries >= 1000)
	{
          _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);

	  return (HTTP_SERVER_ERROR);
	}
      }

      if (*modtime >= ppdinfo.st_mtime)
        return (HTTP_NOT_MODIFIED);
      else
      {
        *modtime = ppdinfo.st_mtime;
	return (HTTP_OK);
      }
    }
  }
#endif /* !WIN32 */

 /*
  * Try finding a printer URI for this printer...
  */

  if (!http)
    if ((http = _cupsConnect()) == NULL)
      return (HTTP_SERVICE_UNAVAILABLE);

  if (!cups_get_printer_uri(http, name, hostname, sizeof(hostname), &port,
                            resource, sizeof(resource), 0))
    return (HTTP_NOT_FOUND);

  DEBUG_printf(("2cupsGetPPD3: Printer hostname=\"%s\", port=%d", hostname,
                port));

 /*
  * Remap local hostname to localhost...
  */

  httpGetHostname(NULL, localhost, sizeof(localhost));

  DEBUG_printf(("2cupsGetPPD3: Local hostname=\"%s\"", localhost));

  if (!_cups_strcasecmp(localhost, hostname))
    strcpy(hostname, "localhost");

 /*
  * Get the hostname and port number we are connected to...
  */

  httpGetHostname(http, http_hostname, sizeof(http_hostname));
  http_port = _httpAddrPort(http->hostaddr);

  DEBUG_printf(("2cupsGetPPD3: Connection hostname=\"%s\", port=%d",
                http_hostname, http_port));

 /*
  * Reconnect to the correct server as needed...
  */

  if (!_cups_strcasecmp(http_hostname, hostname) && port == http_port)
    http2 = http;
  else if ((http2 = httpConnectEncrypt(hostname, port,
                                       cupsEncryption())) == NULL)
  {
    DEBUG_puts("1cupsGetPPD3: Unable to connect to server");

    return (HTTP_SERVICE_UNAVAILABLE);
  }

 /*
  * Get a temp file...
  */

  if (buffer[0])
    fd = open(buffer, O_CREAT | O_TRUNC | O_WRONLY, 0600);
  else
    fd = cupsTempFd(tempfile, sizeof(tempfile));

  if (fd < 0)
  {
   /*
    * Can't open file; close the server connection and return NULL...
    */

    _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);

    if (http2 != http)
      httpClose(http2);

    return (HTTP_SERVER_ERROR);
  }

 /*
  * And send a request to the HTTP server...
  */

  strlcat(resource, ".ppd", sizeof(resource));

  if (*modtime > 0)
    httpSetField(http2, HTTP_FIELD_IF_MODIFIED_SINCE,
                 httpGetDateString(*modtime));

  status = cupsGetFd(http2, resource, fd);

  close(fd);

 /*
  * See if we actually got the file or an error...
  */

  if (status == HTTP_OK)
  {
    *modtime = httpGetDateTime(httpGetField(http2, HTTP_FIELD_DATE));

    if (tempfile[0])
      strlcpy(buffer, tempfile, bufsize);
  }
  else if (status != HTTP_NOT_MODIFIED)
  {
    _cupsSetHTTPError(status);

    if (buffer[0])
      unlink(buffer);
    else if (tempfile[0])
      unlink(tempfile);
  }
  else if (tempfile[0])
    unlink(tempfile);

  if (http2 != http)
    httpClose(http2);

 /*
  * Return the PPD file...
  */

  DEBUG_printf(("1cupsGetPPD3: Returning status %d", status));

  return (status);
}