예제 #1
0
파일: pki_mem.c 프로젝트: Brenhilt/libpki
PKI_MEM *PKI_MEM_get_url_decoded(PKI_MEM *mem)
{
	PKI_MEM *decoded = NULL;
	ssize_t data_size = 0;
	unsigned char *data = NULL;

	int i = 0;
	int enc_idx = 0;

	if(!mem || !mem->data || (mem->size == 0) )
	{
		PKI_ERROR(PKI_ERR_PARAM_NULL, NULL);
		return NULL;
	}

	// Let's allocate a big buffer - same size of the encoded one
	// is enough as URL encoding expands the size (decoded is smaller)
	if ((data = PKI_Malloc(mem->size)) == NULL)
	{
		PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
		return NULL;
	}

	// Let's do the decoding
	for( i = 0; i < mem->size; i++ )
	{
		int p;
		unsigned char k;

		if (sscanf((const char *)&mem->data[i], "%%%2x", &p) > 0)
		{
			k = (unsigned char) p;
			data[enc_idx++] = k;
			i += 2;
		}
		else
		{
			data[enc_idx++] = mem->data[i];
		}
	}

	// Allocates the new PKI_MEM for the decoding operations
	if((decoded = PKI_MEM_new_data(enc_idx, data)) == NULL)
	{
		PKI_Free(data);
		PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
		return NULL;
	}

	// Free the allocated memory
	PKI_Free(data);

	// Returns the newly allocated url-decoded PKI_MEM
	return decoded;
}
예제 #2
0
파일: pki_hmac.c 프로젝트: Brenhilt/libpki
PKI_MEM * PKI_HMAC_new_data(PKI_MEM *data, PKI_MEM *key, PKI_DIGEST_ALG *digest)
{	
	unsigned char *hmac_value = NULL;
	unsigned int hmac_size = 0;

	int key_size = 0;
	size_t data_size = 0;

	PKI_MEM *ret = NULL;

	// Input parameters check
	if (!data || data->size <= 0 || !key || key->size <= 0) 
	{
		PKI_ERROR(PKI_ERR_PARAM_NULL, NULL);
		return NULL;
	}

	// Let's use the correct types for the sizes (for the HMAC call)
	key_size = (int) key->size;
	data_size = (size_t) data->size;

	// Retrieve the data from the OpenSSL library
	hmac_value = HMAC(digest ? digest : PKI_DIGEST_ALG_SHA1, 
		(unsigned char *) key->data, key_size, 
		(unsigned char *) data->data, data_size, 
		NULL, &hmac_size);

	// If no data is returned or size is wrong, let's return null
	if (!hmac_value || hmac_size <= 0)
	{
		if (hmac_value) PKI_Free(hmac_value);
		return NULL;
	}

	// Create a new PKI_MEM object for returning the calculated value
	ret = PKI_MEM_new_data(hmac_size, hmac_value);

	// Return the PKI_MEM object that contains the HMAC value
	return ret;
}
예제 #3
0
파일: pki_mem.c 프로젝트: Brenhilt/libpki
PKI_MEM *PKI_MEM_new_func_bio ( void *obj, int (*func)(BIO *, void *) ) {

	BIO *bio_mem = NULL;
	PKI_MEM *ret = NULL;

	BUF_MEM *bio_mem_ptr = NULL;

	int i = 0;
	size_t size = 0;

	if (!obj || !func ) {
		return NULL;
	}

	if(( bio_mem = BIO_new(BIO_s_mem())) == NULL ) {
		return NULL;
	}

	// fprintf( stderr, "BIO=>%p -- OBJ=>%p\n", bio_mem, obj );
	if((i = func( bio_mem, obj )) <= 0 ) {
		return NULL;
	}

	BIO_get_mem_ptr( bio_mem, &bio_mem_ptr );

	if ( bio_mem_ptr == NULL ) {
		if( bio_mem ) BIO_free ( bio_mem );
		return ( NULL );
	}

	/* Adds the data to the return PKI_MEM */
	size = (size_t) bio_mem_ptr->length;
	ret = PKI_MEM_new_data( size, (unsigned char *) bio_mem_ptr->data);

	/* Closes the BIO and frees the memory */
	if( bio_mem ) BIO_free ( bio_mem );

	return ( ret );

}
예제 #4
0
파일: pki_hmac.c 프로젝트: Brenhilt/libpki
/*
 * \brief Initializes the passed hmac to use the passed key and digest algorithm
 */
int PKI_HMAC_init(PKI_HMAC *hmac, unsigned char *key, size_t key_size, PKI_DIGEST_ALG *digest, HSM *hsm)
{
	if (!hmac) return PKI_ERROR(PKI_ERR_PARAM_NULL, NULL);

	// Free the memory if another key was used
	if (hmac->key) PKI_MEM_free(hmac->key);
	hmac->key = NULL;

	if (hmac->value) PKI_MEM_free(hmac->value);
	hmac->value = NULL;

	// Generate the new PKI_MEM to hold the key data
	hmac->key = PKI_MEM_new_data(key_size, key);
	if (!hmac->key || !hmac->key->data || hmac->key->size <= 0)
	{
		hmac->initialized = 0;
		return PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
	}

	// Sets the algoritm
	hmac->digestAlg = digest ? digest : PKI_DIGEST_ALG_SHA1;

	// Checks if HSM implementation was asked by the developer
	if (hsm)
	{
		PKI_ERROR(PKI_ERR_GENERAL, "Code to support HMAC on HSMs not implemented, yet.");
		hmac->initialized = 0;
		return PKI_ERR;
	}

	// Initializes the Context
	HMAC_Init_ex(&hmac->ctx, (const void *) key, (int) key_size, hmac->digestAlg, NULL);

	// Sets the initialization flag
	hmac->initialized = 1;

	return PKI_OK;
}
예제 #5
0
파일: http_s.c 프로젝트: openca/libpki
PKI_HTTP *PKI_HTTP_get_message (const PKI_SOCKET * sock,
		                        int                timeout,
								size_t             max_size) {

  PKI_HTTP * ret = NULL;

  char * eoh = NULL;
  char * body = NULL;

  ssize_t read = 0; // Keeps track of the single reading
  ssize_t free = 0; // Keeps track of the remaining buffer space
  ssize_t idx = 0; // Keeps track of how much data we poured into MEM
  ssize_t size = 0; // Keeps track of the read data from socket

  // Let's initialize some useful variables (code readability)
  long long content_length = -1;

  // Buffer where to keep the data
  PKI_MEM *m = NULL;

  // Allocates the HTTP message container
  if ((ret = PKI_HTTP_new()) == NULL)
  {
      PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL );
      goto err;
  }
  ret->method = PKI_HTTP_METHOD_UNKNOWN;

  if (max_size > 0)
  {
	  // Allocates a new MEM object
	  m = PKI_MEM_new(max_size + 1);
  }
  else
  {
	  // Allocates the default buffer for HTTP messages
	  m = PKI_MEM_new(HTTP_BUF_SIZE + 1);
  }

	if (m == NULL)
	{
		PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
		return NULL;
	}

	// Sets the free space in the buffer
	free = (ssize_t) m->size - 1;

  // Let's retrieve the data from the socket. Note that this for
  // always read at most 'free' bytes which carries the amount of
  // free space in the buffer -> safe
  for (read = PKI_SOCKET_read(sock, (char *)(&(m->data[idx])), (size_t) free, timeout);
       read > 0;
       read = PKI_SOCKET_read(sock, (char *)(&(m->data[idx])), (size_t) free, timeout))
  {
      // If read is negative, there was an error on the socket
      // let's just report it as an error and move on
      if (read < 0)
      {
    	  if (!eoh)
    	  {
    		  PKI_log_err("Error while reading from socket");
    		  goto err;
    	  }
    	  else
    	  {
    		  // Nothing to read anymore - let's break
    		  PKI_log_err("Nothing to read anymore (read = %d)", read);
    		  break;
    	  }
      }
      else if (read == 0 && eoh)
      {
    	  // No data was read, let's assume the stream is complete and
    	  // break from the for loop
    	  break;
      }

      // Let's be sure there is a NULL-bound limit to the read data
      size += read;
      free -= read;
      m->data[size] = '\x0';

      // If we don't have a header yet, let's look for it
      if (!eoh && ((eoh = __find_end_of_header(m, idx)) != NULL))
      {
    	  // We want the header to finish with just one '\r\n' - since the
    	  // pointer we receive is at the end of the '\r\n\r\n' sequence,
    	  // we need to shrink by 2 bytes
    	  size_t header_size = (size_t) (eoh - (char *) m->data - 2);
    	  ret->head = PKI_MEM_new_data(header_size + 1, m->data);
    	  ret->head->data[header_size] = '\x0';

    	  // If we can not parse the header - we have to return error
    	  if (PKI_ERR == __parse_http_header(ret)) goto err;

    	  // Let's get the pointer to the start of the body
    	  body = eoh + 1;

    	  // Checks for the content-length is in the header - if we have not found it, yet
    	  if (ret->method != PKI_HTTP_METHOD_GET && content_length < 0)
    	  {
    		  char *cnt_len_s = NULL;
    		  if ((cnt_len_s = PKI_HTTP_get_header(ret, "Content-Length" )) != NULL)
    		  {
    			  content_length = atoll(cnt_len_s);
    			  PKI_Free(cnt_len_s);
    			  // PKI_log_debug ( "HTTP Content-Length: %d bytes", content_length);
    		  }
    	  }
      } // End of if (!eoh) ...

      // Updates the start pointer for the next read operation
      idx += read;

      // Let's check if we need to expand the buffer
      if (max_size <= 0)
      {
    	  // We expand the mem if the buffer has less than 2K free
    	  if (free < 2048)
    	  {
    			ssize_t ofs = 0;

    		  if(body)
    		  {
    		    ofs = (ssize_t)(body - (char *)m->data);
          
    		    if(ofs < 0)
    		    {
    		      PKI_log_debug ( "Invalid offset for HTTP body: Start: %p - Body: %p", m->data, body);
    		      PKI_ERROR(PKI_ERR_URI_READ, NULL);
    		      goto err;
    		    }
    		  }

    		  // Grow the memory for the HTTP message
    		  if(content_length > 0 && body && m->size < (size_t)(content_length + ofs))
    		  {
           size_t len = ((size_t)(content_length + ofs) - m->size);

    		    if (PKI_MEM_grow(m, len + 1) == PKI_ERR)
    		    {
    		      PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
    		      goto err;
    		    }
    		    free += (ssize_t)len;
    		  }
    		  else
    		  {
    		    if (PKI_MEM_grow(m, HTTP_BUF_SIZE) == PKI_ERR)
    		    {
    		      PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
    		      goto err;
    		    }
    		    free += HTTP_BUF_SIZE;
    		  }

    		  // Let's update the pointer to the body
    		  if(body) body = (char *)m->data + ofs;
    	  }
      }

      // Let's check if we need to perform the next read or not
      if (eoh && ret->method == PKI_HTTP_METHOD_GET)
      {
    	  // We do not need to wait for any other read as GETs do not have
    	  // a full body
    	  break;
      }
      else if ((content_length >= 0) && (&m->data[size] - (unsigned char *)body >= content_length))
      {
    	  // Here we have received the full body (since the size of the body corresponds or exceeds the
    	  // contents of the Content-Length: header line), therefore we can safely get out of the cycle
    	  break;
      }

  } /* End of for..loop */

  // Here we should have both the eoh and the body - if not, there was
  // an error and we return the malformed request message
  if (!eoh)
  {
	  // PKI_log_err ( "Read data (so far): %d bytes - Last read: %d bytes", idx, read);
	  PKI_ERROR(PKI_ERR_URI_READ, NULL);
	  goto err;
  }

  // Sets some HTTP specific data
  ret->location = PKI_HTTP_get_header ( ret, "Location" );
  ret->type     = PKI_HTTP_get_header ( ret, "Content-Type" );

  if (ret->method != PKI_HTTP_METHOD_GET && content_length > 0 && body)
  {
	  ssize_t body_start = (ssize_t)(body - (char *)m->data);
	  ssize_t body_size = idx - body_start;

	  if (body_start < 0 || body_size < 0)
	  {
		  PKI_log_err ( "Invalid offset for HTTP body - body_start: %d bytes - body_size: %d bytes", body_start, body_size);
		  PKI_ERROR(PKI_ERR_URI_READ, NULL);
		  goto err;
	  }
 
	  //Check if Content-Length > 0 but body_size is 0
	  if (body_size == 0) goto err; 

	  // Let's allocate the body for the HTTP message (if any)
	  ret->body = PKI_MEM_new_data((size_t)body_size+1, (unsigned char *)body);
	  if(ret->body == NULL)
	  {
		PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
		goto err;
	  }
	  ret->body->size = (size_t) body_size;
  }
  else
  {
	  ret->body = PKI_MEM_new_null();
  }

  // Let's free the buffer memory
  if (m) PKI_MEM_free(m);

  // Now we can return the HTTP message
  return ret;

err:

	// First we free the return message
	if (ret) PKI_HTTP_free(ret);

	// We then free the buffer memory object
	if (m) PKI_MEM_free(m);

	return NULL;
}
예제 #6
0
PKI_X509_OCSP_REQ * ocspd_req_get_socket ( int connfd, OCSPD_CONFIG *ocspd_conf)
{
	PKI_X509_OCSP_REQ 	*req = NULL;
	PKI_X509_OCSP_REQ_VALUE *req_val = NULL;

	PKI_IO			*mem = NULL;
	PKI_MEM			*pathmem = NULL;
	PKI_MEM 		*b64mem = NULL;

	PKI_SOCKET		sock;

	size_t maxsize  = 0;
	maxsize = (size_t) ocspd_conf->max_req_size;

	PKI_HTTP *http_msg = NULL;

	if ( connfd <= 0 ) return NULL;

	// Initialize the sock structure
	sock.ssl = NULL;
	PKI_SOCKET_set_fd ( &sock, connfd );

	http_msg = PKI_HTTP_get_message(&sock, (int) ocspd_conf->max_timeout_secs, maxsize);
	if (http_msg == NULL)
	{
		PKI_log_err ("Network Error while reading Request!");
		return NULL;
	};

	/* If method is METHOD_GET we shall de-urlify the buffer and get the
	   right begin (keep in mind there might be a path set in the config */

	if( http_msg->method == PKI_HTTP_METHOD_GET )
	{
		char *req_pnt = NULL;

		if (http_msg->path == NULL)
		{
			PKI_log_err("Malformed GET request");
			goto err;
		}

		req_pnt = http_msg->path;
		while(strchr(req_pnt, '/') != NULL)
		{
			req_pnt = strchr(req_pnt, '/') + 1;
		}

		pathmem = PKI_MEM_new_data(strlen(req_pnt), (unsigned char *) req_pnt);
		if (pathmem == NULL)
		{
			PKI_log_err("Memory Allocation Error!");
			goto err;
		}

		if((b64mem = PKI_MEM_url_decode (pathmem, 0)) == NULL)
		{
			PKI_log_err("Memory Allocation Error!");
			PKI_MEM_free(pathmem);
			pathmem = NULL; // Safety
			goto err;
		}

		if (PKI_MEM_B64_decode(b64mem, 76) == PKI_ERR )
		{
			PKI_log_err ("Error decoding B64 Mem");
			PKI_MEM_free ( b64mem );
			b64mem = NULL;
			req_pnt = http_msg->path;
			while(req_pnt[0] == '/')
			{
				req_pnt=req_pnt + 1;
			}
			b64mem = PKI_MEM_new_data(strlen(req_pnt), (unsigned char *) req_pnt);
			if (b64mem == NULL)
			{
				PKI_log_err("Memory Allocation Error!");
				goto err;
			}
			if (PKI_MEM_B64_decode(b64mem, 76) == PKI_ERR )
			{
				PKI_log_err ("Error decoding B64 Mem");
				PKI_MEM_free ( b64mem );
				goto err;
			}
		}

		if((mem = BIO_new_mem_buf(b64mem->data, (int) b64mem->size )) == NULL)
		{
			PKI_log_err("Memory Allocation Error");
			PKI_MEM_free ( b64mem );
			goto err;
		}

		if((req_val = d2i_OCSP_REQ_bio(mem, NULL)) == NULL ) {
				PKI_log_err("Can not parse REQ");
		}

		PKI_MEM_free ( b64mem );
		BIO_free (mem);

	}
	else if ( http_msg->method == PKI_HTTP_METHOD_POST)
	{
		mem = BIO_new_mem_buf(http_msg->body->data, (int) http_msg->body->size);
		if (mem == NULL)
		{
			PKI_log_err( "Memory Allocation Error");
			goto err;
		}
		else
		{
			if ((req_val = d2i_OCSP_REQ_bio(mem, NULL)) == NULL)
			{
				PKI_log_err("Can not parse REQ");
			}
			BIO_free (mem);
		}
	}
	else
	{
		PKI_log_err ( "HTTP Method not supported");
		goto err;
	}

	if ( !req_val ) goto err;

	req = PKI_X509_new_value(PKI_DATATYPE_X509_OCSP_REQ, req_val, NULL);
	if (req == NULL)
	{
		PKI_log_err ("Can not generate a new X509_OCSP_REQ");
		goto err;
	}

	if ( http_msg ) PKI_HTTP_free ( http_msg );

	return (req);

err:
	if (http_msg) PKI_HTTP_free(http_msg);

	return NULL;
}
예제 #7
0
파일: pki_mem.c 프로젝트: Brenhilt/libpki
PKI_MEM *PKI_MEM_dup ( PKI_MEM *mem ) {
	if (!mem) return NULL;

	return PKI_MEM_new_data ( mem->size, mem->data );
}