Beispiel #1
0
int  /* returns -1 if error, 0 if verfy fail, and 1 if verify OK */
smime_verify_cert(const char* ca_cert_pem, const char* cert_pem)
{
  X509* ca_cert = NULL;
  X509* cert = NULL;
  int ret = -1;
  if (!ca_cert_pem || !cert_pem) GOTO_ERR("NULL arg(s)");
  if (!(ca_cert = extract_certificate(ca_cert_pem))) goto err;
  if (!(cert = extract_certificate(cert_pem))) goto err;
  ret = verify_cert(ca_cert, cert);
err:
  if (ca_cert) X509_free(ca_cert);
  if (cert) X509_free(cert);
  return ret;
}
Beispiel #2
0
int
verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
{
  int ret = 0;
  struct tls_session *session;
  SSL *ssl;
  struct gc_arena gc = gc_new();

  /* get the tls_session pointer */
  ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
  ASSERT (ssl);
  session = (struct tls_session *) SSL_get_ex_data (ssl, mydata_index);
  ASSERT (session);

  cert_hash_remember (session, ctx->error_depth,
      x509_get_sha1_hash(ctx->current_cert, &gc));

  /* did peer present cert which was signed by our root cert? */
  if (!preverify_ok)
    {
      /* get the X509 name */
      char *subject = x509_get_subject(ctx->current_cert, &gc);

      if (subject)
	{
	  /* Remote site specified a certificate, but it's not correct */
	  msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s",
	      ctx->error_depth,
	      X509_verify_cert_error_string (ctx->error),
	      subject);
	}

      ERR_clear_error();

      session->verified = false;
      goto cleanup;
    }

  if (SUCCESS != verify_cert(session, ctx->current_cert, ctx->error_depth))
    goto cleanup;

  ret = 1;

cleanup:
  gc_free(&gc);

  return ret;
}
int
verify_callback (void *session_obj, x509_crt *cert, int cert_depth,
    int *flags)
{
  struct tls_session *session = (struct tls_session *) session_obj;
  struct gc_arena gc = gc_new();

  ASSERT (cert);
  ASSERT (session);

  session->verified = false;

  /* Remember certificate hash */
  cert_hash_remember (session, cert_depth, x509_get_sha1_hash(cert, &gc));

  /* did peer present cert which was signed by our root cert? */
  if (*flags != 0)
    {
      char *subject = x509_get_subject(cert, &gc);

      if (subject)
	msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, flags=%x, %s", cert_depth, *flags, subject);
      else
	msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, flags=%x, could not extract X509 "
	      "subject string from certificate", *flags, cert_depth);

      /* Leave flags set to non-zero to indicate that the cert is not ok */
    }
  else if (SUCCESS != verify_cert(session, cert, cert_depth))
    {
      *flags |= BADCERT_OTHER;
    }

  gc_free(&gc);

  /*
   * PolarSSL-1.2.0+ expects 0 on anything except fatal errors.
   */
  return 0;
}
static int exchange_certificates(struct openssl_session_auth_context* ctx, char** client_certificate, u32* client_certificate_length, char** server_certificate, u32* server_certificate_length, struct in_addr* remote_addr) {
    int ret, server_cert_verification_result_code, client_cert_verification_result_code;
    char* common_name = NULL;
    u32 common_name_length;

    /* Load server certificate */
    if( load_cert(module_context->path_to_publickey, server_certificate, server_certificate_length) || *server_certificate_length <= 0 ) {
        printf("Failed to load public key: %s\n", module_context->path_to_publickey);
        goto failed;
    }

    /* Just check if we are able to verify certificate against our own CA */
    if ( verify_cert(*server_certificate, *server_certificate_length,  &common_name, &common_name_length) ) {
        printf("Failed to verify own certificate against the CA. Cert file: %s\n", module_context->path_to_publickey);
        goto failed;
    }

    /* Send server certificate length */
    if ( write_u32(ctx, *server_certificate_length) != 4) {
        printf("Failed to send server certificate length\n");
        goto failed;
    }

    /* Send server certificate */
    if ( openssl_local_write(ctx, *server_certificate, *server_certificate_length) != *server_certificate_length ) {
        printf("Failed to send server certificate\n");
        goto failed;
    }

    /* Reads verification result of server certificate validation by the client */
    server_cert_verification_result_code = read_u32(ctx);

    if ( server_cert_verification_result_code == READ_ERROR ) {
        printf("Failed to read client response on server certificate validation\n");
        goto failed;
    } else if ( server_cert_verification_result_code == 0 ) {
        printf("Client failed to validate server certificate\n");
        goto failed;
    }

    /* Reads client certificate length */
    *client_certificate_length = read_u32(ctx);
    if ( *client_certificate_length == READ_ERROR ) {
        printf("Failed to read client certificate length\n");
        goto failed;
    }

    /* Reads client certificate */
    *client_certificate = malloc(*client_certificate_length);
    if ( *client_certificate == NULL )
        goto failed;
    if ( openssl_local_read(ctx, *client_certificate_length, *client_certificate, client_certificate_length) < *client_certificate_length ) {
        printf( "Failed to read client certificate\n");
        goto failed;
    }

    /* Verifies client certificate against CA */
    ret = verify_cert(*client_certificate, *client_certificate_length, &common_name, &common_name_length);
    if ( ret ) {
        client_cert_verification_result_code = 0;
        printf("Failed to validate client certificate against CA\n");
    } else {
        /* Certificate is signed by the trusted CA, now we have to check whether the remote node ip matches certificate ip */
        char remote_ip[100];
        inet_ntop(AF_INET, remote_addr, remote_ip, 100);
        //printf("Remote addr: %s\n",remote_ip);
        if ( strcmp(remote_ip, common_name) != 0 ) {
            client_cert_verification_result_code = 0;
            printf("Client certificate is signed by CA, but is issued for a different client. Current client is %s, but the certificate is for %s\n", remote_ip, common_name);
        } else {
            client_cert_verification_result_code = 1;
        }
    }

    if ( client_cert_verification_result_code == 1) {
        ret = 0;
    } else {
        ret = -1;
    }

    /* Send client certificate verification result */
    if ( write_u32(ctx, client_cert_verification_result_code) != 4 ) {
        printf("Failed to send server certificate length\n");
        goto failed;
    }

    goto done;

failed:
    ret = -1;
done:
    free(common_name);
    return ret;
};
Beispiel #5
0
int
main (int argc, char **argv)
{
    int		 retval;
    PRFileDesc	*in_file;
    FILE	*out_file;	/* not PRFileDesc until SECU accepts it */
    int		 crequest, dresponse;
    int		 prequest, presponse;
    int		 ccert, vcert;
    const char	*db_dir, *date_str, *cert_usage_str, *name;
    const char	*responder_name, *responder_url, *signer_name;
    PRBool	 add_acceptable_responses, add_service_locator;
    SECItem	*data = NULL;
    PLOptState	*optstate;
    SECStatus	 rv;
    CERTCertDBHandle *handle = NULL;
    SECCertUsage cert_usage;
    PRTime	 verify_time;
    CERTCertificate *cert = NULL;
    PRBool ascii = PR_FALSE;

    retval = -1;		/* what we return/exit with on error */

    program_name = PL_strrchr(argv[0], '/');
    program_name = program_name ? (program_name + 1) : argv[0];

    in_file = PR_STDIN;
    out_file = stdout;

    crequest = 0;
    dresponse = 0;
    prequest = 0;
    presponse = 0;
    ccert = 0;
    vcert = 0;

    db_dir = NULL;
    date_str = NULL;
    cert_usage_str = NULL;
    name = NULL;
    responder_name = NULL;
    responder_url = NULL;
    signer_name = NULL;

    add_acceptable_responses = PR_FALSE;
    add_service_locator = PR_FALSE;

    optstate = PL_CreateOptState (argc, argv, "AHLPR:S:V:d:l:pr:s:t:u:w:");
    if (optstate == NULL) {
	SECU_PrintError (program_name, "PL_CreateOptState failed");
	return retval;
    }

    while (PL_GetNextOpt (optstate) == PL_OPT_OK) {
	switch (optstate->option) {
	  case '?':
	    short_usage (program_name);
	    return retval;

	  case 'A':
	    add_acceptable_responses = PR_TRUE;
	    break;

	  case 'H':
	    long_usage (program_name);
	    return retval;

	  case 'L':
	    add_service_locator = PR_TRUE;
	    break;

	  case 'P':
	    presponse = 1;
	    break;

	  case 'R':
	    dresponse = 1;
	    name = optstate->value;
	    break;

	  case 'S':
	    ccert = 1;
	    name = optstate->value;
	    break;

	  case 'V':
	    vcert = 1;
	    name = optstate->value;
	    break;

	  case 'a':
	    ascii = PR_TRUE;
	    break;

	  case 'd':
	    db_dir = optstate->value;
	    break;

	  case 'l':
	    responder_url = optstate->value;
	    break;

	  case 'p':
	    prequest = 1;
	    break;

	  case 'r':
	    crequest = 1;
	    name = optstate->value;
	    break;

	  case 's':
	    signer_name = optstate->value;
	    break;

	  case 't':
	    responder_name = optstate->value;
	    break;

	  case 'u':
	    cert_usage_str = optstate->value;
	    break;

	  case 'w':
	    date_str = optstate->value;
	    break;
	}
    }

    PL_DestroyOptState(optstate);

    if ((crequest + dresponse + prequest + presponse + ccert + vcert) != 1) {
	PR_fprintf (PR_STDERR, "%s: must specify exactly one command\n\n",
		    program_name);
	short_usage (program_name);
	return retval;
    }

    if (vcert) {
	if (cert_usage_str == NULL) {
	    PR_fprintf (PR_STDERR, "%s: verification requires cert usage\n\n",
			program_name);
	    short_usage (program_name);
	    return retval;
	}

	rv = cert_usage_from_char (cert_usage_str, &cert_usage);
	if (rv != SECSuccess) {
	    PR_fprintf (PR_STDERR, "%s: invalid cert usage (\"%s\")\n\n",
			program_name, cert_usage_str);
	    long_usage (program_name);
	    return retval;
	}
    }

    if (ccert + vcert) {
	if (responder_url != NULL || responder_name != NULL) {
	    /*
	     * To do a full status check, both the URL and the cert name
	     * of the responder must be specified if either one is.
	     */
	    if (responder_url == NULL || responder_name == NULL) {
		if (responder_url == NULL)
		    PR_fprintf (PR_STDERR,
				"%s: must also specify responder location\n\n",
				program_name);
		else
		    PR_fprintf (PR_STDERR,
				"%s: must also specify responder name\n\n",
				program_name);
		short_usage (program_name);
		return retval;
	    }
	}

	if (date_str != NULL) {
	    rv = DER_AsciiToTime (&verify_time, (char *) date_str);
	    if (rv != SECSuccess) {
		SECU_PrintError (program_name, "error converting time string");
		PR_fprintf (PR_STDERR, "\n");
		long_usage (program_name);
		return retval;
	    }
	} else {
	    verify_time = PR_Now();
	}
    }

    retval = -2;		/* errors change from usage to runtime */

    /*
     * Initialize the NSPR and Security libraries.
     */
    PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
    db_dir = SECU_ConfigDirectory (db_dir);
    rv = NSS_Init (db_dir);
    if (rv != SECSuccess) {
	SECU_PrintError (program_name, "NSS_Init failed");
	goto prdone;
    }
    SECU_RegisterDynamicOids();

    if (prequest + presponse) {
	MAKE_FILE_BINARY(stdin);
	data = read_file_into_item (in_file, siBuffer);
	if (data == NULL) {
	    SECU_PrintError (program_name, "problem reading input");
	    goto nssdone;
	}
    }

    if (crequest + dresponse + presponse + ccert + vcert) {
	handle = CERT_GetDefaultCertDB();
	if (handle == NULL) {
	    SECU_PrintError (program_name, "problem getting certdb handle");
	    goto nssdone;
	}

	/*
	 * It would be fine to do the enable for all of these commands,
	 * but this way we check that everything but an overall verify
	 * can be done without it.  That is, that the individual pieces
	 * work on their own.
	 */
	if (vcert) {
	    rv = CERT_EnableOCSPChecking (handle);
	    if (rv != SECSuccess) {
		SECU_PrintError (program_name, "error enabling OCSP checking");
		goto nssdone;
	    }
	}

	if ((ccert + vcert) && (responder_name != NULL)) {
	    rv = CERT_SetOCSPDefaultResponder (handle, responder_url,
					       responder_name);
	    if (rv != SECSuccess) {
		SECU_PrintError (program_name,
				 "error setting default responder");
		goto nssdone;
	    }

	    rv = CERT_EnableOCSPDefaultResponder (handle);
	    if (rv != SECSuccess) {
		SECU_PrintError (program_name,
				 "error enabling default responder");
		goto nssdone;
	    }
	}
    }

#define NOTYET(opt)							\
	{								\
	    PR_fprintf (PR_STDERR, "%s not yet working\n", opt);	\
	    exit (-1);							\
	}

    if (name) {
        cert = find_certificate(handle, name, ascii);
    }

    if (crequest) {
	if (signer_name != NULL) {
	    NOTYET("-s");
	}
	rv = create_request (out_file, handle, cert, add_service_locator,
			     add_acceptable_responses);
    } else if (dresponse) {
	if (signer_name != NULL) {
	    NOTYET("-s");
	}
	rv = dump_response (out_file, handle, cert, responder_url);
    } else if (prequest) {
	rv = print_request (out_file, data);
    } else if (presponse) {
	rv = print_response (out_file, data, handle);
    } else if (ccert) {
	if (signer_name != NULL) {
	    NOTYET("-s");
	}
	rv = get_cert_status (out_file, handle, cert, name, verify_time);
    } else if (vcert) {
	if (signer_name != NULL) {
	    NOTYET("-s");
	}
	rv = verify_cert (out_file, handle, cert, name, cert_usage, verify_time);
    }

    if (rv != SECSuccess)
	SECU_PrintError (program_name, "error performing requested operation");
    else
	retval = 0;

nssdone:
    if (cert) {
        CERT_DestroyCertificate(cert);
    }

    if (data != NULL) {
	SECITEM_FreeItem (data, PR_TRUE);
    }

    if (handle != NULL) {
 	CERT_DisableOCSPDefaultResponder(handle);        
 	CERT_DisableOCSPChecking (handle);
    }

    if (NSS_Shutdown () != SECSuccess) {
	retval = 1;
    }

prdone:
    PR_Cleanup ();
    return retval;
}