src/platform_unix.c
author Edouard Tisserant
Mon, 11 Jul 2016 18:11:36 +0200
changeset 838 70119c10b0f5
parent 814 91f317ce921f
child 841 bb25b36f52d6
permissions -rw-r--r--
Fixing #100 : 31 bit random number generator with static seed (Android)
     1 #define _POSIX_C_SOURCE 200809L
     2 
     3 #include <string.h>
     4 #include <stdlib.h>
     5 #include <assert.h>
     6 #include <sys/stat.h>
     7 #include <sys/types.h>
     8 #include <fcntl.h>
     9 
    10 #include "platform_unix.h"
    11 
    12 #define MAX_PATH 1024
    13 #define LOCAL_DB_FILENAME ".pEp_management.db"
    14 #define SYSTEM_DB_FILENAME "system.db"
    15 
    16 #ifndef bool
    17 #define bool int
    18 #define true 1
    19 #define false 0
    20 #endif
    21 
    22 #ifdef ANDROID
    23 char *stpncpy(char *dst, const char *src, size_t n)
    24 {
    25     if (n != 0) {
    26         char *d = dst;
    27         const char *s = src;
    28 
    29         dst = &dst[n];
    30         do {
    31             if ((*d++ = *s++) == 0) {
    32                 dst = d - 1;
    33                 /* NUL pad the remaining n-1 bytes */
    34                 while (--n != 0)
    35                     *d++ = 0;
    36                 break;
    37             }
    38         } while (--n != 0);
    39     }
    40     return (dst);
    41 }
    42 
    43 char *stpcpy(char *dst, const char *src)
    44 {
    45     for (;; ++dst, ++src) {
    46         *dst = *src;
    47         if (*dst == 0)
    48             break;
    49     }
    50     return dst;
    51 }
    52 
    53 long int random(void)
    54 {
    55     time_t t = time(NULL);
    56     static unsigned short xsubi[3];
    57     xsubi[0] = ((unsigned short *)t)[0];
    58     xsubi[1] = ((unsigned short *)t)[1];
    59     xsubi[2] = ((unsigned short *)t)[2];
    60 
    61     return nrand48(xsubi);
    62 }
    63 
    64 const char *android_system_db(void)
    65 {
    66     static char buffer[MAX_PATH];
    67     static bool done = false;
    68 
    69     if (!done) {
    70         char *tw_env;
    71         if(tw_env = getenv("TRUSTWORDS")){
    72             char *p = stpncpy(buffer, tw_env, MAX_PATH);
    73             ssize_t len = MAX_PATH - (p - buffer) - 2;
    74 
    75             if (len < strlen(SYSTEM_DB_FILENAME)) {
    76                 assert(0);
    77                 return NULL;
    78             }
    79 
    80             *p++ = '/';
    81             strncpy(p, SYSTEM_DB_FILENAME, len);
    82             done = true;
    83         }else{
    84             return NULL;
    85         }
    86 
    87     }
    88     return buffer;
    89 }
    90 #endif
    91 
    92 const char *unix_local_db(void)
    93 {
    94     static char buffer[MAX_PATH];
    95     static bool done = false;
    96 
    97     if (!done) {
    98         char *home_env;
    99         if((home_env = getenv("HOME"))){
   100             char *p = stpncpy(buffer, home_env, MAX_PATH);
   101             ssize_t len = MAX_PATH - (p - buffer) - 2;
   102 
   103             if (len < strlen(LOCAL_DB_FILENAME)) {
   104                 assert(0);
   105                 return NULL;
   106             }
   107 
   108             *p++ = '/';
   109             strncpy(p, LOCAL_DB_FILENAME, len);
   110             done = true;
   111         }else{
   112             return NULL;
   113         }
   114 
   115     }
   116     return buffer;
   117 }
   118 
   119 static const char *gpg_conf_path = ".gnupg";
   120 static const char *gpg_conf_name = "gpg.conf";
   121 static const char *gpg_agent_conf_name = "gpg-agent.conf";
   122 static const char *gpg_conf_empty = "# Created by pEpEngine\n";
   123 
   124 static bool ensure_gpg_home(const char **conf, const char **home){
   125     static char path[MAX_PATH];
   126     static char dirname[MAX_PATH];
   127     static bool done = false;
   128 
   129     if (!done) {
   130         char *p;
   131         ssize_t len;
   132         char *gpg_home_env = getenv("GNUPGHOME");
   133         char *home_env = getenv("HOME");
   134 
   135         if(gpg_home_env){
   136 
   137             p = stpncpy(path, gpg_home_env, MAX_PATH);
   138             len = MAX_PATH - (p - path) - 2;
   139 
   140             if (len < strlen(gpg_conf_name))
   141             {
   142                 assert(0);
   143                 return false;
   144             }
   145 
   146         }else if(home_env){
   147 
   148             p = stpncpy(path, home_env, MAX_PATH);
   149             len = MAX_PATH - (p - path) - 3;
   150 
   151             if (len < strlen(gpg_conf_path) + strlen(gpg_conf_name))
   152             {
   153                 assert(0);
   154                 return false;
   155             }
   156 
   157             *p++ = '/';
   158             strncpy(p, gpg_conf_path, len);
   159             p += strlen(gpg_conf_path);
   160             len -= strlen(gpg_conf_path) - 1;
   161 
   162         }else{
   163 
   164             assert(0);
   165             return false;
   166         }
   167 
   168         strncpy(dirname, path, MAX_PATH);
   169         *p++ = '/';
   170         strncpy(p, gpg_conf_name, len);
   171 
   172         if(access(path, F_OK)){ 
   173             int fd;
   174             if(access(dirname, F_OK )) { 
   175                 mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR);
   176             }
   177 
   178             fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
   179 
   180             if(fd>0) {
   181                 write(fd, gpg_conf_empty, strlen(gpg_conf_empty));
   182                 close(fd);
   183             }
   184         }
   185 
   186         done = true;
   187     }
   188 
   189     if(conf) *conf=path;
   190     if(home) *home=dirname;
   191 
   192     return true;
   193 }
   194 
   195 static bool ensure_gpg_agent_conf(const char **agent_conf){
   196     static char agent_path[MAX_PATH];
   197     static bool done = false;
   198 
   199     if (!done) {
   200         const char *dirname;
   201 
   202         if (!ensure_gpg_home(NULL, &dirname)) /* Then dirname won't be set. */
   203             return false;
   204 
   205         char *p;
   206         p = stpncpy(agent_path, dirname, MAX_PATH);
   207         
   208         ssize_t len = MAX_PATH - (p - agent_path) - 2;
   209 
   210         if (len < strlen(gpg_agent_conf_name))
   211         {
   212             assert(0);
   213             return false;
   214         }
   215 
   216         *p++ = '/';
   217      
   218         strncpy(p, gpg_agent_conf_name, len);
   219 
   220         if(access(agent_path, F_OK)){ 
   221             int fd;
   222             if(access(dirname, F_OK )) { 
   223                 mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR);
   224             }
   225 
   226             fd = open(agent_path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
   227 
   228             if(fd>0) {
   229                 write(fd, gpg_conf_empty, strlen(gpg_conf_empty));
   230                 close(fd);
   231             }
   232         }
   233         done = true;
   234     }
   235     if(agent_conf) *agent_conf=agent_path;
   236 
   237     return true;
   238 }
   239 
   240 const char *gpg_conf(void)
   241 {
   242     const char *conf;
   243     if(ensure_gpg_home(&conf, NULL))
   244         return conf;
   245     return NULL;
   246 }
   247 
   248 const char *gpg_home(void)
   249 {
   250     const char *home;
   251     if(ensure_gpg_home(NULL, &home))
   252         return home;
   253     return NULL;
   254 }
   255 
   256 const char *gpg_agent_conf(void)
   257 {
   258     const char *agent_conf;
   259     if(ensure_gpg_agent_conf(&agent_conf))
   260         return agent_conf;
   261     return NULL;
   262 }