毕业设计之LDAP存储X509证书

http://blog.chinaunix.net/uid-20055870-id-1737019.html

LDAP存储证书
毕业程序需要在一个月内完成,而openssl编程资料奇缺,时间仓促,完成过程中肯定存在很多问题,没有对程序进行优化,所以这里我们主要说明程序的实现过程。欢迎大家批评指正。
该文件主要完成把x509证书存储到LDAP库中。
1、由openssl生成相应的证书
2、使用openssl库函数读取证书
3、根据证书的类型,使用LDAP API保存证书到不同的目录中。
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
#include<ldap.h>
#include<lber.h>
#include<unistd.h>
#include <sys/stat.h>
BIO *bio_err=NULL;
BIO *STDout=NULL;
void print_name(BIO *out, char *title, X509_NAME *nm, unsigned long lflags)
{
 char *buf;
 char mline = 0;
 int indent = 0;
 if(title) BIO_puts(out, title);
 if((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
  mline = 1;
  indent = 4;
 }
 if(lflags == XN_FLAG_COMPAT) {
  buf = X509_NAME_oneline(nm, 0, 0);
  BIO_puts(out, buf);
  BIO_puts(out, "\n");
  OPENSSL_free(buf);
 } else {
  if(mline) BIO_puts(out, "\n");
  X509_NAME_print_ex(out, nm, indent, lflags);
  BIO_puts(out, "\n");
 }
}
int myX509V3_extensions_print(BIO *bp, char *title, STACK_OF(X509_EXTENSION) *exts, unsigned index, unsigned long flag, int indent)
{
 int i, j;
 if(sk_X509_EXTENSION_num(exts) <= 0) return 1;
 if(title) 
  {
  BIO_printf(bp,"%*s%s:",indent, "", title);
  indent += 4;
  }
  if(sk_X509_EXTENSION_num(exts)<=index||index<=0)
  {
   for (i=0; i<sk_X509_EXTENSION_num(exts); i++)
    {
     ASN1_OBJECT *obj;
     X509_EXTENSION *ex;
     ex=sk_X509_EXTENSION_value(exts, i);
     if (indent && BIO_printf(bp,"%*s",indent, "") <= 0) return 0;
     obj=X509_EXTENSION_get_object(ex);
     i2a_ASN1_OBJECT(bp,obj);
     j=X509_EXTENSION_get_critical(ex);
     if (BIO_printf(bp,": %s\n",j?"critical":"","") <= 0)
      return 0;
     if(!X509V3_EXT_print(bp, ex, flag, indent + 4))
    {
      BIO_printf(bp, "%*s", indent + 4, "");
      M_ASN1_OCTET_STRING_print(bp,ex->value);
    }
     if (BIO_write(bp,"\n",1) <= 0) return 0;
  }
 }
 else
 {   
     indent=0;
     ASN1_OBJECT *obj;
     X509_EXTENSION *ex;
     ex=sk_X509_EXTENSION_value(exts, index);
     if (indent && BIO_printf(bp,"%*s",indent, "") <= 0) return 0;
     obj=X509_EXTENSION_get_object(ex);
     i2a_ASN1_OBJECT(bp,obj);
     j=X509_EXTENSION_get_critical(ex);
     if (BIO_printf(bp,": %s",j?"critical":"","") <= 0)
      return 0;
     if(!X509V3_EXT_print(bp, ex, flag, indent))
    {
      //BIO_printf(bp, "%*s", indent + 4, "");
      M_ASN1_OCTET_STRING_print(bp,ex->value);
    }
     if (BIO_write(bp,"",1) <= 0) return 0;
 }
 return 1;
}
int main(int argc, char **argv)
{
 STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
 bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
 unsigned long nmflag = 0;
 char *infile=argv[1];
 printf("sore cert name is %s\n",infile);
 BIO *in;
 in=BIO_new(BIO_s_file());
 if (in == NULL)
 {
   BIO_printf(bio_err,"create in file error!\n");
   goto end;
 }
 if (BIO_read_filename(in,infile) <= 0)
 {
   BIO_printf(bio_err,"File:%s is reading error!\n",infile);
   BIO_free(in);
   goto end;
 }
 X509 *x = NULL;
  if (!PEM_read_bio_X509(in, &x, 0, NULL))
  {
     BIO_printf(bio_err,"PEM loading to X509 error!\n");
     BIO_free(in);
     goto end;
  }
  //打印需要保存的证书的内容
 
  BIO *mem = BIO_new(BIO_s_mem());
  char *ptr=NULL;
  int length=0;
  //print_name(mem, NULL,X509_get_issuer_name(x), nmflag);
  
  char cn_buf[256]={'\0'};
  char sn_buf[256]={'\0'};
  char sern_buf[256]={'\0'};
  char nb_buf[256]={'\0'};
  char na_buf[256]={'\0'};
  char ext_buf[512]={'\0'};
  char certType[32]={'\0'};
  print_name(mem, NULL, X509_get_subject_name(x), nmflag);
  length = BIO_get_mem_data(mem, &ptr);
  memcpy(sn_buf,ptr,length-1);/*去掉一个换行符*/
  printf("length=%d,subject=%s\n",length,sn_buf);
  BIO_free(mem);
  
  getValueFromStr1(sn_buf, "CN", cn_buf);
  
  mem = BIO_new(BIO_s_mem());
  i2a_ASN1_INTEGER(mem,x->cert_info->serialNumber);
  length = BIO_get_mem_data(mem, &ptr);
  memcpy(sern_buf,ptr,length);
  printf("length=%d,serialNumber=%s\n",length,sern_buf);
  BIO_free(mem);
  
  mem = BIO_new(BIO_s_mem());
  ASN1_TIME_print(mem,X509_get_notBefore(x));
  length = BIO_get_mem_data(mem, &ptr);
  memcpy(nb_buf,ptr,length);
  printf("length=%d,notBefore=%s\n",length,nb_buf);
  BIO_free(mem);
  
  mem = BIO_new(BIO_s_mem());
  ASN1_TIME_print(mem,X509_get_notAfter(x));
  length = BIO_get_mem_data(mem, &ptr);
  memcpy(na_buf,ptr,length);
  printf("length=%d,notAfter=%s\n",length,na_buf);
  BIO_free(mem);
  
  mem = BIO_new(BIO_s_mem());
  X509V3_CTX ctx2;
  STACK_OF(X509_EXTENSION) *extensions=x->cert_info->extensions;
  myX509V3_extensions_print(mem, NULL, extensions, 1, 0, 0);
  length = BIO_get_mem_data(mem, &ptr);
  memcpy(ext_buf,ptr,length);
  printf("length=%d,extension=%s\n",length,ext_buf);
  getValueFromStr(ext_buf,"CertType",certType);
  printf("CertType=%s\n",certType);
  /*
  print_name(STDout, "issuer= ",X509_get_issuer_name(x), nmflag);
  print_name(STDout, "subject= ",X509_get_subject_name(x), nmflag);
  BIO_puts(STDout,"serialNumber=");
  i2a_ASN1_INTEGER(STDout,x->cert_info->serialNumber);
  BIO_printf(STDout,"\n");
  BIO_puts(STDout,"notBefore=");
 ASN1_TIME_print(STDout,X509_get_notBefore(x));
 BIO_puts(STDout,"\n");
 BIO_puts(STDout,"notAfter=");
 ASN1_TIME_print(STDout,X509_get_notAfter(x));
  BIO_puts(STDout,"\n");
  
  X509V3_CTX ctx2;
  STACK_OF(X509_EXTENSION) *extensions=x->cert_info->extensions;
  //X509V3_extensions_print(STDout, "X509v3 extensions", extensions, 0, 0);
  myX509V3_extensions_print(STDout, NULL, extensions, 1, 0, 0);
  */
  //开始保存证书
  LDAPMod cert_attribute,cn_attribute,sn_attribute,serialNumber_attribute,certType_attribute,certNotBefore_attribute,certNotAfter_attribute,userCertificate_attribute,objectClass_attribute;
  printf("cn=%s\n",cn_buf);
  printf("sn=%s\n",sn_buf);
  printf("sern=%s\n",sern_buf);
  printf("nb=%s\n",nb_buf);
  printf("na=%s\n",na_buf);
  char *cn_vals[]={cn_buf,NULL};
  char *sn_vals[]={sn_buf,NULL};
  char *serialNumber_vals[]={sern_buf,NULL};
  char *certNotBefore_vals[]={nb_buf,NULL};
  char *certNotAfter_vals[]={na_buf,NULL};
  char *objectClass_vals[]={certType,NULL};
  
  //pem转换成der格式保存
  int len;
  char *Cert_buf,*byte;
  len = i2d_X509(x, NULL);
  byte = (char*)malloc(len);
  if (byte == NULL)
  {
   BIO_printf(bio_err,"malloc error!\n");
   BIO_free(in);
   goto end;
  }
  Cert_buf = byte;
  //printf("len=%d",len);
  //printf("cert_buff=%s",Cert_buf);
  i2d_X509(x, &byte);//证书的DER编码二进制格式保存在buf中
  struct berval cert_berval;
  struct berval *cert_values[2];
 cert_attribute.mod_op=LDAP_MOD_ADD | LDAP_MOD_BVALUES;
 cert_attribute.mod_type="userCertificate;binary";
 cert_berval.bv_len = len;
 cert_berval.bv_val = Cert_buf;
 cert_values[0] = &cert_berval;
 cert_values[1] = NULL;
 cert_attribute.mod_values =cert_values;
 
  cn_attribute.mod_op=LDAP_MOD_ADD;
  cn_attribute.mod_type="cn";
  cn_attribute.mod_values=cn_vals;
  sn_attribute.mod_op=LDAP_MOD_ADD;
  sn_attribute.mod_type="sn";
  sn_attribute.mod_values=sn_vals;
  
  serialNumber_attribute.mod_op=LDAP_MOD_ADD;
  serialNumber_attribute.mod_type="serialNumber";
  serialNumber_attribute.mod_values=serialNumber_vals;
  certNotBefore_attribute.mod_op=LDAP_MOD_ADD;
  certNotBefore_attribute.mod_type="certNotBefore";
  certNotBefore_attribute.mod_values=certNotBefore_vals;

  certNotAfter_attribute.mod_op=LDAP_MOD_ADD;
  certNotAfter_attribute.mod_type="certNotAfter";
  certNotAfter_attribute.mod_values=certNotAfter_vals;
  objectClass_attribute.mod_op=LDAP_MOD_ADD;
  objectClass_attribute.mod_type="objectClass";
  objectClass_attribute.mod_values=objectClass_vals;

  LDAPMod *mods[8];
  mods[0]=&cn_attribute;
  mods[1]=&sn_attribute;
  mods[2]=&serialNumber_attribute;
  mods[3]=&certNotBefore_attribute;
  mods[4]=&certNotAfter_attribute;
  mods[5]=&cert_attribute;
  mods[6]=&objectClass_attribute;
  mods[7]=NULL;
  
  char new_dn[100]={'\0'};
  strcpy(new_dn,"cn=");
  strcpy(&new_dn[3],cn_buf);
  strcpy((new_dn+strlen(cn_buf)+3),",ou=");
  strcpy((new_dn+strlen(new_dn)),certType);
  strcpy((new_dn+strlen(new_dn)),",dc=Jlu,dc=Grid");
  printf("dn=%s\n",new_dn);
  storecert(mods,new_dn);
end:
  //BIO_printf(bio_err,"program is exiting!\n"); 
 return 0;
}
//保存证书
int storecert(LDAPMod *mods,char *new_dn)
{
 //服务器配置
 LDAP *ld;
  int res;
  int authmod=LDAP_AUTH_SIMPLE;
  char *ldap_host="localhost";
  char *user_dn="cn=root,dc=Jlu,dc=Grid";
  char *user_pw="lgl135";
  printf("starting store cert!\n");
 //初始化ldap
  if ((ld=ldap_init(ldap_host,LDAP_PORT))==NULL)
  {
    perror("Failure of ldap_init");
    exit(EXIT_FAILURE);
  }
  printf("initing done!\n");
  //绑定ldap
  if(ldap_bind_s(ld,user_dn,user_pw,authmod)!=LDAP_SUCCESS)
  {
    ldap_perror(ld,"Failure of ldap_bind");
    exit(EXIT_FAILURE);
  }
  printf("ldap_bind_s done!\n");
  //添加记录
  if(ldap_add_s(ld,new_dn,mods)!=LDAP_SUCCESS)
 {
   ldap_perror(ld,"Failure of ldap_add_s");
   exit(EXIT_FAILURE);
  }
  printf("cert has been saved in LDAP server.\n");

  //(void)ldap_msgfree(ldap_message_set);
  //关闭绑定
  res=ldap_unbind_s(ld);
  if(res!=0){
   fprintf(stderr,"ldap_unbind_s failed:%s\n",ldap_err2string(res));
   exit(EXIT_FAILURE);
  }
  return EXIT_SUCCESS;
}
int getValueFromStr(char *src, char *title, char *rt)
{
    int slen=strlen(src);
    int tlen=strlen(title),start=0,end = 0;
 int length =0;
 int i=0;
 if(strcmp(title,"CertType")==0)
 {
   for(i=0;i<(slen);i++)
   {
   if(src[i]=='[')
   {
    end=i;
    break;
   }
  }
  if(end)
   length = end;
  else
   length = (i);
  strncpy(rt,src+strlen("Netscape Comment: "),length-strlen("Netscape Comment: "));   
    return length;
     
    }
    else if(strcmp(title,"CertValue")==0)
 {
        for(i=0;i<(slen);i++)
        {
   if(src[i]=='[')
   {
    start=i+1;
    break;
   }
  }
  for(i=start;i<slen;i++)
        {
   if(*(src+i)==']')
   { 
    end=i;
    break;
   }
   
        }
        if(start == 0 ||end ==0)
  {
   printf("The value no right!\n");
   return 0;
  }
        else{
   length =(end-start);
   strncpy(rt,&src[start],(length));
   rt[length]='\0';
   return length;
        }
  
    }
 else
 {
  return -1;
 }
    
    
}
int getValueFromStr1(char *src, char *title, char *rt)
{
    int slen=strlen(src);
    int tlen=strlen(title),start,end;
   int i=0;
    for(i=0;i<(slen-tlen);i++)
    {
     if(strncmp((src+i),title,tlen) == 0)
     {
      if(src[i+tlen]=='=')
      {
       start=i+tlen+1;
       break;
      }
      
     }
     
    }
   if(start == 0) return 0;
    for(i=start;i<slen;i++)
    {
     if(*(src+i)=='\/')
     { 
       end=i;
       break;
     }
        
    }
    end=i;
    int realLength=0;
    if(end == slen)
       realLength=(end-start)-1;
    else
       realLength=(end-start);
    memcpy(rt,&src[start],realLength);
    rt[realLength]='\0';
    return (end-start+1);
    
}
编译生成可执行文件
gcc -I /usr/local/ssl/include -I/u01/apps/ladp2.3/include   -L/usr/local/ssl/lib/ 
-L/u01/apps/ladp2.3/lib -lldap -llber -o storecert storecert.c

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值