⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pubcrypt.c

📁 Linux下的飞鸽传书
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Following codes(particularly check_secure_directory function)  * are derived from  * ``Secure Programming Cookbook for C and C++''. * URL:http://www.oreilly.com/catalog/secureprgckbk/  *     http://www.secureprogramming.com/ *  * Licensing Information can be obtain from following URL: * *  http://www.secureprogramming.com/?action=license * * Copyright  2003 by John Viega and Matt Messier. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met:  * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the *  documentation and/or other materials provided with the distribution. * * 3. Neither the name of the developer of this software nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <dirent.h>#include <glib.h>#include <openssl/bn.h>#include <openssl/sha.h>#include <openssl/md5.h>#include <openssl/rsa.h>#include <openssl/engine.h>#include <openssl/err.h>#include <openssl/rand.h>#include <openssl/pem.h>#include "common.h"GStaticMutex dir_check_mutex = G_STATIC_MUTEX_INIT;GStaticMutex file_check_mutex = G_STATIC_MUTEX_INIT;GStaticMutex rsa_key_mutex = G_STATIC_MUTEX_INIT;static RSA *rsa_keys[RSA_KEY_MAX];static int key2ipmsg_key_type[]={  IPMSG_RSA_2048,  IPMSG_RSA_1024,  IPMSG_RSA_512,  -1};static intget_rsa_key_index(unsigned long cap,int *indp){  int rc;  int index;  if ( (!indp) ||  (!(cap & RSA_CAPS)) )    return -EINVAL;  switch(cap)    {    case IPMSG_RSA_512:      index=RSA_KEY_INDEX_512;      break;    case IPMSG_RSA_1024:      index=RSA_KEY_INDEX_1024;      break;    case IPMSG_RSA_2048:      index=RSA_KEY_INDEX_2048;      break;    default:      g_assert_not_reached();      break;    }  *indp=index;  return 0;}static intopen_key_file_for_read(int *fd_p,const unsigned char *file) {  int rc;  int fd;  uid_t uid;  struct stat fbuff,lbuff;  if ( (!fd_p) || (!file) )    return -EINVAL;  g_static_mutex_lock(&file_check_mutex); /* 厳密にいえば不要 */  fd=open(file,O_RDONLY);  if (fd<0) {    rc=-errno;    goto unlock_out;  }  rc=fstat(fd,&fbuff);  if (rc<0) {    rc=-errno;    goto error_out;  }  rc=lstat(file,&lbuff);  if (rc<0) {    rc=-errno;    goto error_out;  }  uid=geteuid();  /*   * 偏執的ではあるが, リンクでないことを確認する   */  rc=-EPERM;  if ( (lbuff.st_mode != fbuff.st_mode) ||       (lbuff.st_ino != fbuff.st_ino) ||       (lbuff.st_dev != fbuff.st_dev) )    goto error_out;  /*   * 本人以外に書き込めないことを確認する   */  if ( ((fbuff.st_mode) & RSA_DIR_INVALID_FLAGS))    goto error_out;  /*   * rootが所有するファイルには, 書き込まない   */  if ( (fbuff.st_uid) && (fbuff.st_uid != uid) )    goto error_out;  rc=0;  *fd_p=fd; unlock_out:  g_static_mutex_unlock(&file_check_mutex); /* 厳密にいえば不要 */  return rc; error_out:  close(fd);  g_static_mutex_unlock(&file_check_mutex); /* 厳密にいえば不要 */  return rc;}static intopen_key_file_for_write(int *fd_p,const unsigned char *file) {  int rc;  int fd;  uid_t uid;  struct stat fbuff,lbuff;  if ( (!fd_p) || (!file) )    return -EINVAL;  g_static_mutex_lock(&file_check_mutex); /* 厳密にいえば不要 */  fd=open(file,O_CREAT|O_EXCL|O_WRONLY,S_IRUSR|S_IWUSR);  if (fd<0){    if (errno != EEXIST) {      rc=-errno;      goto unlock_out;    }else{      fd=open(file, O_WRONLY);      if (fd<0){	rc=-errno;	goto unlock_out;      }    }  }  rc=fstat(fd,&fbuff);  if (rc<0) {    rc=-errno;    goto error_out;  }  rc=lstat(file,&lbuff);  if (rc<0) {    rc=-errno;    goto error_out;  }  uid=geteuid();  /*   * 偏執的ではあるが, リンクでないことを確認する   */  rc=-EPERM;  if ( (lbuff.st_mode != fbuff.st_mode) ||       (lbuff.st_ino != fbuff.st_ino) ||       (lbuff.st_dev != fbuff.st_dev) )    goto error_out;  /*   * 本人以外に書き込めないことを確認する   */  if ( ((fbuff.st_mode) & RSA_DIR_INVALID_FLAGS))    goto error_out;  /*   * rootが所有するファイルには, 書き込まない   */  if ( (fbuff.st_uid) && (fbuff.st_uid != uid) )    goto error_out;  rc=0;  *fd_p=fd; unlock_out:  g_static_mutex_unlock(&file_check_mutex); /* 厳密にいえば不要 */  return rc; error_out:  close(fd);  g_static_mutex_unlock(&file_check_mutex); /* 厳密にいえば不要 */  return rc;}static intcheck_secure_directory(const unsigned char *dir) {  DIR *fd,*start;  int rc;  char new_dir[PATH_MAX+1];  uid_t uid;  struct stat fbuff,lbuff;  void *ref;  g_static_mutex_lock(&dir_check_mutex); /* 厳密にいえば不要 */  start = opendir(".");  if (!start) {    rc=-errno;    goto unlock_out;  }  rc=lstat(dir,&lbuff);  if (rc<0) {    rc=-errno;    goto close_dir_out;  }  uid=geteuid();  do{    if (chdir(dir)) {      rc=-errno;      goto ret_to_work_dir_out;    }    fd=opendir(".");    if (!fd)      goto ret_to_work_dir_out;    rc=fstat(dirfd(fd),&fbuff);    closedir(fd);    if (rc<0) {      rc=-errno;      goto ret_to_work_dir_out;    }    /*     * 偏執的ではあるが, リンクでないことを確認する     */    rc=-EPERM;    if ( (lbuff.st_mode != fbuff.st_mode) ||	 (lbuff.st_ino != fbuff.st_ino) ||	 (lbuff.st_dev != fbuff.st_dev) )      goto ret_to_work_dir_out;    /*     * 本人以外に書き込めないことを確認する     */    if ( ((fbuff.st_mode) & RSA_DIR_INVALID_FLAGS))      goto ret_to_work_dir_out;    /*     * rootが所有するファイルには, 書き込まない     */    if ( (fbuff.st_uid) && (fbuff.st_uid != uid) )      goto ret_to_work_dir_out;    /*     *1つ上のディレクトリを探査する     */    dir="..";    rc=lstat(dir,&lbuff);    if (rc<0) {      rc=-errno;      goto ret_to_work_dir_out;    }    memset(new_dir,0,PATH_MAX+1);    ref=getcwd(new_dir,PATH_MAX+1); /* 次に調査するディレクトリの				    *  親ディレクトリを獲得				    */    if (!ref)      goto ret_to_work_dir_out;  }while(new_dir[1]);  if (!new_dir[1])    rc=0;  else    rc=-EPERM; ret_to_work_dir_out:  fchdir(dirfd(start)); close_dir_out:  closedir(start); unlock_out:  g_static_mutex_unlock(&dir_check_mutex); /* 厳密にいえば不要 */  return rc;}static intstore_private_key(const char *fpath,RSA *rsa,pem_password_cb *cb){  int rc;  int fd;  FILE *fp;  EVP_CIPHER *enc=NULL;  char errbuf[1024];  if ( (!fpath) || (!rsa) )    return -EINVAL;  rc=open_key_file_for_write(&fd,fpath);  if (rc)    goto error_out;  fp=fdopen(fd,"w");  if (!fp) {    rc=-errno;    goto error_out;  }  if (cb)     enc=(EVP_CIPHER *)EVP_des_ede_cbc();    rc=PEM_write_RSAPrivateKey(fp,rsa,enc,NULL,0,cb,NULL);    if (!rc){    rc=ERR_get_error();    err_out("Can not store private key %s : err=%s\n", fpath, ERR_error_string(rc, errbuf));    rc=-rc;  }  rc=fclose(fp);  if (rc)    rc=-errno;  rc=0;   error_out:  return rc;}static intstore_public_key(const char *fpath,RSA *rsa){  int rc;  int fd;  FILE *fp;  EVP_CIPHER *enc=NULL;  char errbuf[1024];  if ( (!fpath) || (!rsa) )    return -EINVAL;  rc=open_key_file_for_write(&fd,fpath);  if (rc<0)    goto error_out;  fp=fdopen(fd,"w");  if (!fp) {    rc=-errno;    goto error_out;  }    rc=PEM_write_RSAPublicKey(fp,rsa);  if (!rc){    rc=ERR_get_error();    err_out("Can not store public key %s : err=%s\n", fpath, ERR_error_string(rc, errbuf));    rc=-rc;  }  rc=fclose(fp);  if (rc)    rc=-errno;  rc=0;   error_out:  return rc;}static intload_private_key(const char *fpath,RSA **rsa,pem_password_cb *cb){  int rc;  int fd;  FILE *fp;  char errbuf[1024];  void *ref;  if ( (!fpath) || (!rsa) )    return -EINVAL;  rc=open_key_file_for_read(&fd,fpath);  if (rc)    goto error_out;      fp=fdopen(fd,"r");  if (!fp) {    rc=-errno;    goto error_out;  }  ref=PEM_read_RSAPrivateKey(fp,rsa,cb,NULL);    if (!ref){    rc=ERR_get_error();    err_out("Can not load private key %s : err=%s\n", fpath, ERR_error_string(rc, errbuf));    rc=-rc;  }  rc=fclose(fp);  if (rc)    rc=-errno;  rc=0;   error_out:  return rc;}static intload_public_key(const char *fpath,RSA **rsa){  int rc;  int fd;  FILE *fp;  EVP_CIPHER *enc=NULL;  char errbuf[1024];  RSA *ref;  if ( (!fpath) || (!rsa) )    return -EINVAL;  rc=open_key_file_for_read(&fd,fpath);  if (rc)    goto error_out;  fp=fdopen(fd,"r");  if (!fp) {    rc=-errno;    goto error_out;  }    ref=PEM_read_RSAPublicKey(fp,rsa,NULL,NULL);  if (!ref){    rc=ERR_get_error();    err_out("Can not read public key %s : err=%s\n", fpath, ERR_error_string(rc, errbuf));    rc=-rc;  }  rc=fclose(fp);  if (rc)    rc=-errno;  rc=0;   error_out:  return rc;}static int generate_rsa_key(RSA **rsa_p,unsigned long key_type) {  int rc;  RSA *rsa;  char errbuf[1024];  int keylen;  int retry_count=RSA_KEYGEN_RETRY;  if (!rsa_p)    return -EINVAL;  rc=pcrypt_get_rsa_key_length(key_type,&keylen);  if (rc)    return rc;    dbg_out("generate key length:%d\n",keylen);  /* RSA 鍵生成 */ retry:  rsa = RSA_generate_key(keylen, RSA_F4, NULL, NULL);  if ( rsa == NULL ){    rc=ERR_get_error();    dbg_out("in generate_key: err=%s\n", ERR_error_string(rc, errbuf));    return (ERR_get_error()*-1);  }  if (RSA_check_key(rsa)>0){    *rsa_p=rsa;    rc=0;  } else {    RSA_free(rsa);    rc=ERR_get_error();    err_out("This is invalid key: err=%s\n", ERR_error_string(rc, errbuf));    --retry_count;    if (retry_count)      goto retry;  }  return rc;}static intconvert_peer_key(const char *peer_e,const char *peer_n,RSA **rsa){  int rc;  RSA *pubkey=NULL;  BIGNUM *bn_e=NULL,*bn_n=NULL;  size_t size_in_byte;  if ( (!peer_e) || (!peer_n) || (!rsa) )    return -EINVAL;  pubkey = RSA_new();  if (!pubkey)    return -ENOMEM;  rc=-ENOMEM;  bn_e = BN_new();  if (!bn_e)    goto free_pubkey_out;  bn_n = BN_new();  if (!bn_n)    goto free_bn_e_out;  rc=BN_hex2bn(&bn_e, peer_e);  if (!rc)    goto free_bn_e_out;  rc=BN_hex2bn(&bn_n, peer_n);  if (!rc)    goto free_bn_e_out;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -