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