Пример #1
0
/*
 * This routine intializes an EST context, which can later
 * be used to issue commands to an EST server.
 */
static EST_CTX * setup_est_context (void)
{
    EST_CTX *ectx;
    EST_ERROR rv;

    /*
     * Initialize an EST context.  We must provide the trust
     * anchor certs at this time.
     */
    ectx = est_client_init(cacerts, cacerts_len, EST_CERT_FORMAT_PEM, NULL);
    if (!ectx) {
        printf("\nUnable to initialize EST context.  Aborting!!!\n");
        exit(1);
    }
        
    /*
     * Set the local authentication credentials.  We're not using
     * a certificate to identify ourselves to the server.  We're 
     * simply hard-coding the userID and password, which will be
     * used for HTTP authentication.
     */
    rv = est_client_set_auth(ectx, est_http_uid, est_http_pwd, NULL, NULL);
    if (rv != EST_ERR_NONE) {
        printf("\nUnable to configure client authentication.  Aborting!!!\n");
        printf("EST error code %d (%s)\n", rv, EST_ERR_NUM_TO_STR(rv));
        exit(1);
    }        

    if (srp) {
	rv = est_client_enable_srp(ectx, SRP_MINIMAL_N, est_srp_uid, est_srp_pwd);
	if (rv != EST_ERR_NONE) {
	    printf("\nUnable to enable SRP.  Aborting!!!\n");
	    exit(1);
	}        
    }

    if (token_auth_mode) {
        rv = est_client_set_auth_cred_cb(ectx, auth_credentials_token_cb);
        if (rv != EST_ERR_NONE) {
            printf("\nUnable to register token auth callback.  Aborting!!!\n");
            exit(1);
        }        
    }
    
    /*
     * Specify the EST server address and TCP port#
     */
    rv = est_client_set_server(ectx, est_server, est_port, NULL);
    if (rv != EST_ERR_NONE) {
        printf("\nUnable to configure server address.  Aborting!!!\n");
        printf("EST error code %d (%s)\n", rv, EST_ERR_NUM_TO_STR(rv));
        exit(1);
    }        

    return (ectx);
}
Пример #2
0
static void do_operation ()
{
    EST_CTX *ectx;
    unsigned char *pkcs7;
    int pkcs7_len = 0;
    int rv;
    char file_name[MAX_FILENAME_LEN];
    unsigned char *new_client_cert;
    int retry_delay = 0;
    time_t retry_time = 0;
    char *operation;

    ectx = est_client_init(cacerts, cacerts_len,
                           EST_CERT_FORMAT_PEM,
                           client_manual_cert_verify);
    if (!ectx) {
        printf("\nUnable to initialize EST context.  Aborting!!!\n");
        exit(1);
    }

    rv = est_client_set_read_timeout(ectx, read_timeout);
    if (rv != EST_ERR_NONE) {
        printf("\nUnable to configure read timeout from server.  Aborting!!!\n");
        printf("EST error code %d (%s)\n", rv, EST_ERR_NUM_TO_STR(rv));
        exit(1);
    }

    rv = est_client_set_auth(ectx, est_http_uid, est_http_pwd, client_cert, client_priv_key);
    if (rv != EST_ERR_NONE) {
        printf("\nUnable to configure client authentication.  Aborting!!!\n");
        printf("EST error code %d (%s)\n", rv, EST_ERR_NUM_TO_STR(rv));
        exit(1);
    }


    if (srp) {
        rv = est_client_enable_srp(ectx, 1024, est_srp_uid, est_srp_pwd);
        if (rv != EST_ERR_NONE) {
            printf("\nUnable to enable SRP.  Aborting!!!\n");
            exit(1);
        }
    }

    if (token_auth_mode) {
        rv = est_client_set_auth_cred_cb(ectx, auth_credentials_token_cb);
        if (rv != EST_ERR_NONE) {
	    printf("\nUnable to register token auth callback.  Aborting!!!\n");
	    exit(1);
        }        
    }            

    est_client_set_server(ectx, est_server, est_port);

    if (getcert) {
        operation = "Get CA Cert";

        rv = est_client_get_cacerts(ectx, &pkcs7_len);
        if (rv == EST_ERR_NONE) {
            if (verbose) {
                printf("\nGet CA Cert success\n");
            }

            /*
             * allocate a buffer to retrieve the CA certs
             * and get them copied in
             */
            pkcs7 = malloc(pkcs7_len);
            rv = est_client_copy_cacerts(ectx, pkcs7);

            /*
             * Dump the retrieved cert to stdout
             */
            if (verbose) {
                dumpbin(pkcs7, pkcs7_len);
            }

            /*
             * Generate the output file name, which contains the thread ID
             * and iteration number.
             */
            snprintf(file_name, MAX_FILENAME_LEN, "%s/cacert.pkcs7", out_dir);
            write_binary_file(file_name, pkcs7, pkcs7_len);

            free(pkcs7);

        }
    }

    if (enroll && getcsr) {
        operation = "Regular enrollment with server-defined attributes";

        rv = regular_enroll_attempt(ectx);

        if (rv == EST_ERR_CA_ENROLL_RETRY) {

            /*
             * go get the retry period
             */
            rv = est_client_copy_retry_after(ectx, &retry_delay, &retry_time);
            if (verbose) {
                printf("\nretry after period copy rv = %d "
                       "Retry-After delay seconds = %d "
                       "Retry-After delay time = %s\n",
                       rv, retry_delay, ctime(&retry_time) );
            }
            if (rv == EST_ERR_NONE) {
                retry_enroll_delay(retry_delay, retry_time);
            }
            /*
             * now that we're back, try to enroll again
             */
            rv = regular_enroll_attempt(ectx);

        }

    } else if (enroll && !getcsr) {
        operation = "Simple enrollment without server-defined attributes";

        rv = simple_enroll_attempt(ectx);

        if (rv == EST_ERR_CA_ENROLL_RETRY) {

            /*
             * go get the retry period
             */
            rv = est_client_copy_retry_after(ectx, &retry_delay, &retry_time);
            if (verbose) {
                printf("\nretry after period copy rv = %d "
                       "Retry-After delay seconds = %d "
                       "Retry-After delay time = %s\n",
                       rv, retry_delay, ctime(&retry_time) );
            }
            if (rv == EST_ERR_NONE) {
                retry_enroll_delay(retry_delay, retry_time);
            }

            /*
             * now that we're back, try to enroll again
             */
            rv = simple_enroll_attempt(ectx);
        }

    } else if (!enroll && getcsr) {
        operation = "Get CSR attribues";

        rv = regular_csr_attempt(ectx);

    }

    /* Split reenroll from enroll to allow both messages to be sent */
    if (reenroll) {
        operation = "Re-enrollment";

        rv = est_client_reenroll(ectx, client_cert, &pkcs7_len, client_priv_key);
        if (verbose) {
            printf("\nreenroll rv = %d (%s) with pkcs7 length = %d\n",
                   rv, EST_ERR_NUM_TO_STR(rv), pkcs7_len);
        }
        if (rv == EST_ERR_NONE) {
            /*
             * client library has obtained the new client certificate.
             * now retrieve it from the library
             */
            new_client_cert = malloc(pkcs7_len);
            if (new_client_cert == NULL) {
                if (verbose) {
                    printf("\nmalloc of destination buffer for reenroll cert failed\n");
                }
            }

            rv = est_client_copy_enrolled_cert(ectx, new_client_cert);
            if (verbose) {
                printf("\nreenroll copy rv = %d\n", rv);
            }
            if (rv == EST_ERR_NONE) {
                /*
                 * Enrollment copy worked, dump the pkcs7 cert to stdout
                 */
                if (verbose) {
                    dumpbin(new_client_cert, pkcs7_len);
                }
            }

            /*
             * Generate the output file name, which contains the thread ID
             * and iteration number.
             */
            snprintf(file_name, MAX_FILENAME_LEN, "%s/newcert", out_dir);
            save_cert(file_name, new_client_cert, pkcs7_len);
            free(new_client_cert);
        }
    }

    if (rv != EST_ERR_NONE) {
        /*
         * something went wrong.
         */
        printf("\n%s failed with code %d (%s)\n",
               operation, rv, EST_ERR_NUM_TO_STR(rv));
    }

    est_destroy(ectx);

    ERR_clear_error();
    ERR_remove_thread_state(NULL);
}
Пример #3
0
/*
 * get_client_ctx() performs a search through a ordered array.
 * The key for the search is the current thread id and the value returned
 * is the client context that's been created for this thread.  If no
 * entry exists in the array for this thread id, a new one is created.
 */
static EST_CTX *get_client_ctx (EST_CTX *p_ctx) 
{
    EST_CTX *c_ctx = NULL;
    EST_ERROR rv;
    unsigned long cur_threadid = 0;
    unsigned long cur_pid = getpid();
    CLIENT_CTX_LU_NODE_T *found_node;
    unsigned long zero_threadid = 0x0;
    CLIENT_CTX_LU_NODE_T *empty_node;
    int empty_index;

    /*
     * TODO: This is really returning a pointer to an opaque value, so
     * what's being used here is typically a pointer in pthread based
     * environments and not the actual pthread id.  The only helper API to
     * access the actual id is pthread_equal().  If this must be used, then
     * the array search would best be changed to a linear search.
     * We mix in the PID of the current process with the thread ID in
     * case the application is forking new processes (e.g. NGINX).  
     */
#ifndef DISABLE_PTHREADS
#ifdef __MINGW32__
    cur_threadid = (unsigned long) GetCurrentThreadId();
#else
    cur_threadid = (unsigned long) pthread_self();
#endif
#endif
    cur_threadid += cur_pid;

    found_node = (CLIENT_CTX_LU_NODE_T *) bsearch(&cur_threadid,
                                                  p_ctx->client_ctx_array,
                                                  cur_max_ctx_array,
                                                  sizeof(CLIENT_CTX_LU_NODE_T),
                                                  bsearch_compare);
    if (found_node == NULL) {
        
        /*
         * need to allocate a context and get it ready to be used.
         */
        c_ctx = est_client_init(p_ctx->ca_chain_raw, p_ctx->ca_chain_raw_len,
                                EST_CERT_FORMAT_PEM, NULL);
        if (c_ctx == NULL) {
            EST_LOG_ERR("Unable to allocate and initialize EST client context for proxy use");
            return (NULL);
        }

        /*
         * The name is a bit misleading.  The identity cert and private
         * key used for proxy mode are the ones stored in the server_cert and
         * server_priv_key, however they are used in both directions, so here
         * when setting up the client side, it looks mixed up.  Might want to
         * change the name in context to hold these.
         */
        rv = est_client_set_auth(c_ctx, p_ctx->userid, p_ctx->password,
                                 p_ctx->server_cert, p_ctx->server_priv_key);
        if (rv != EST_ERR_NONE) {
            EST_LOG_ERR("Unable to set authentication configuration in the client context for proxy use");
	    est_destroy(c_ctx);
            return (NULL);
	}        

        rv = est_client_set_auth_cred_cb(c_ctx, p_ctx->auth_credentials_cb);
        if (rv != EST_ERR_NONE) {
            EST_LOG_ERR("Unable to register authentication credential callback.");
            return (NULL);
        }

	rv = est_client_set_server(c_ctx, p_ctx->est_server, p_ctx->est_port_num);
        if (rv != EST_ERR_NONE) {
            EST_LOG_ERR("Unable to set the upstream server configuration in the client context for proxy use");
	    est_destroy(c_ctx);
            return (NULL);
	}

        rv = est_client_set_read_timeout(c_ctx, p_ctx->read_timeout);
        if (rv != EST_ERR_NONE) {
            EST_LOG_ERR("Unable to set the SSL read timeout in the client context");
	    est_destroy(c_ctx);
            return (NULL);
	}        

        /*
         * make sure there's room for another entry
         */
        empty_node = (CLIENT_CTX_LU_NODE_T *) bsearch(&zero_threadid,
                                                      p_ctx->client_ctx_array,
                                                      cur_max_ctx_array,
                                                      sizeof(CLIENT_CTX_LU_NODE_T),
                                                      bsearch_compare);

        if (empty_node == NULL) {
            /*
             * we're out of space.  allocate a new array and copy over what's
             * already there.  Double the size of the current one.
             */
            CLIENT_CTX_LU_NODE_T *temp_array;
            
            cur_max_ctx_array *= 2;
            temp_array = (CLIENT_CTX_LU_NODE_T *) malloc(sizeof(CLIENT_CTX_LU_NODE_T)*cur_max_ctx_array);
            memset(temp_array, 0, sizeof(CLIENT_CTX_LU_NODE_T)*cur_max_ctx_array);                
            memcpy(temp_array, p_ctx->client_ctx_array,
		   sizeof(CLIENT_CTX_LU_NODE_T)*cur_max_ctx_array/2);
            free(p_ctx->client_ctx_array);
            p_ctx->client_ctx_array = temp_array;
            
            qsort(p_ctx->client_ctx_array, cur_max_ctx_array,
                  sizeof(CLIENT_CTX_LU_NODE_T), 
                  bsearch_compare);

            empty_node = (CLIENT_CTX_LU_NODE_T *) bsearch(&zero_threadid,
                                                          p_ctx->client_ctx_array,
                                                          cur_max_ctx_array,
                                                          sizeof(CLIENT_CTX_LU_NODE_T),
                                                          bsearch_compare);
        }
        empty_index = (int) (empty_node - p_ctx->client_ctx_array);

        /*
         * add to the array and sort it into its proper place
         */
        p_ctx->client_ctx_array[empty_index].threadid = cur_threadid;
        p_ctx->client_ctx_array[empty_index].client_ctx = c_ctx;
        
        qsort(p_ctx->client_ctx_array, cur_max_ctx_array,
              sizeof(CLIENT_CTX_LU_NODE_T), 
              bsearch_compare);
    } else {
        /*
         * the entry was found in the tree, return the client context for this pid
         */
        c_ctx = found_node->client_ctx;
    }
    
    return(c_ctx);   
}        
Пример #4
0
/*! @brief est_proxy_set_auth_cred_cb() is used by an application to register
  its callback function. 
    
  @param ctx EST context obtained from the est_proxy_init() call.
  @param auth_credentials_cb  Function pointer to the application layer callback

  The registered callback function is used by the EST client library to obtain
  authentication credentials.  The application can provide authentication
  credentials during initialization if they are available, such as the userid
  and password used with HTTP basic authentication.  During the processing of
  a request, the EST client library will call this application callback in the
  event that it does not have the authentication credentials that are being
  requested by the EST server.

  The callback function definition must match the following function
  prototype,

  int (*auth_credentials_cb)(EST_HTTP_AUTH_HDR *auth_credentials);

  auth_credentials - A pointer to a EST_HTTP_AUTH_HDR structure.  The
                     structure is provided by the EST library and the callback
                     function fills in the specific credentials being
                     requested.  These credential values must be passed in the
                     format in which they will be sent to the server, that is,
                     the EST client library will perform no reformatting of
                     these credentials.  Ownership of the memory holding these
                     credential values is transferred from the application
                     layer to the EST library when the application layer
                     returns these values to the EST library.  This allows the
                     EST library to free up this memory as soon as it is done
                     using these values.
                         
  The return value from the callback must be one of the following values:

  EST_HTTP_AUTH_CRED_SUCCESS - If the callback was able to provide the
                               requested credentials.
  EST_HTTP_AUTH_CRED_NOT_AVAILABLE - If the callback could not provide the
                                     requested credentials.

  The auth_credentials_cb parameter can be set to NULL to reset the callback
  function.
  
  All string parameters are NULL terminated strings.
    
  @return EST_ERROR.
  EST_ERR_NONE - Success.
  EST_ERR_NO_CTX
*/
EST_ERROR est_proxy_set_auth_cred_cb (EST_CTX *ctx, auth_credentials_cb callback)
{
    return(est_client_set_auth_cred_cb(ctx, callback));
}