该结构用于检查证书用途,它定义在x509v3.h中,如下:

typedef struct x509_purpose_st

{

              int purpose;

              int trust;

              int flags;

              int (*check_purpose)(const struct x509_purpose_st *,const X509 *, int);

              char *name;

              char *sname;

              void *usr_data;

} X509_PURPOSE;

purpose为证书用途IDcheck_purpose为检查证书用途函数。基本的用途IDx509v3.h中定义,如下:

#define X509_PURPOSE_SSL_CLIENT             1

#define X509_PURPOSE_SSL_SERVER            2

#define X509_PURPOSE_NS_SSL_SERVER      3

#define X509_PURPOSE_SMIME_SIGN           4

#define X509_PURPOSE_SMIME_ENCRYPT    5

#define X509_PURPOSE_CRL_SIGN                6

#define X509_PURPOSE_ANY                          7

#define X509_PURPOSE_OCSP_HELPER          8

Opensslx509v3/v3_purp.c中维护了两个表,用来检查各种证书用途。如下:

标准表:

static X509_PURPOSE xstandard[] = {

       {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, check_purpose_ssl_client, "SSL client", "sslclient", NULL},

       {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ssl_server, "SSL server", "sslserver", NULL},

       {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL},

       {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, "S/MIME signing", "smimesign", NULL},

      {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL},

       {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, "CRL signing", "crlsign", NULL},

       {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any", NULL},

       {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, "OCSP helper", "ocsphelper", NULL},

};

扩展表:

static STACK_OF(X509_PURPOSE) *xptable = NULL;

扩展表由用户通过X509_PURPOSE_add函数来添加。

当用户需要检查某个证书用途时,先查表,找到对应的X509_PURPOSE,然后调用其check_purpose函数来判断证书用途是否合法。

检查证书用途的函数为int X509_check_purpose(X509 *x, int id, int ca),该函数用于检查证书的用途。x为待检查待证书,id为证书用途NIDca表明x是否是ca证书。

基本用法如下:

#include <openssl/x509.h>

#include <openssl/x509v3.h>

int    main()

{

       X509             *x=0;

       int                  id,len,ret;

       FILE              *fp;

       unsigned charbuf[5000],*p;

 

       fp=fopen("root.cer","rb");

       len=fread(buf,1,5000,fp);

       fclose(fp);

 

       p=buf;

       d2i_X509(&x,&p,len);

       id=X509_PURPOSE_OCSP_HELPER;

       ret=X509_check_purpose(x,id,0);

       if(ret==1)

       {

              printf("purpose check ok!\n");

       }

       else 

       {

              printf("purpose check failed!\n");

       }

       X509_free(x);

       return 0;

}

如果输入的id小于0,不做任何检查,只是证书的各个扩展项信息写入到将X509数据结构中。

另外本函数支持其他用途的验证,示例如下:

#include <openssl/x509v3.h>

int    cb_check_tsa(X509_PURPOSE *purpose,const X509 *x,int isCA)

{

              int           flag;

      

              printf("------------my check!-----------------\n");

              /*  针对x添加判断函数 */

              flag=*((int *)(purpose->usr_data));

              if(flag)

                     return 1;  /* 由此功能 */

              else

                     return 0;  /* 无此功能 */

}

int    main()

{

              X509                    *x=0;

              int                         id,len,ret;

              FILE                     *fp;

              unsigned charbuf[5000],*p;

              int                         tsaFlag;

 

              tsaFlag=1;

              ret=X509_PURPOSE_add(1000,1000,0,cb_check_tsa,"tsa","checkTsa",&tsaFlag);

              fp=fopen("root.cer","rb");

              len=fread(buf,1,5000,fp);

              fclose(fp);

              p=buf;

              d2i_X509(&x,&p,len);

              id=1000;

              ret=X509_check_purpose(x,id,0);

              if(ret==1)

              {

                     printf("purpose check ok!\n");

              }

              else 

              {

                     printf("purpose check failed!\n");

              }

              X509_free(x);

              return 0;

}

本程序通过调用函数X509_PURPOSE_add添加一个X509_PURPOSE内部数据结构,然后再验证证书是否有此用途。用户所要实现的为X509_PURPOSE中的回调函数,在此回调函数中,用户根据证书信息来判断证书是否有此用途。如果用户还需要其他的信息才能作出判断,可以另外获取X509_PURPOSE数据结构中的usr_datausr_data为一个void指针类型。用户可在调用X509_PURPOSE_add函数时将它写入对应的X509_PURPOSE数据结构(上例中的tsaFlag)