Back to index

im-sdk  12.3.91
clientenv.c
Go to the documentation of this file.
00001 /* This module is derived from the original libiiimp.
00002    And the file name is role-data-client.c.
00003    In order to inspect client environment, currently use
00004    this file also in libiiimcf.  But it will be at least
00005    partly rewritten mainly for procuring portability. */
00006 
00007 
00008 #if defined(HAVE_CONFIG_H)
00009 #include "config.h"
00010 #endif
00011 
00012 #include <stdlib.h>
00013 #include <ctype.h>
00014 #include <string.h>
00015 #include <sys/types.h>
00016 #include <unistd.h>
00017 #include <pwd.h>
00018 #include <sys/param.h>
00019 #include <sys/stat.h>
00020 #include <sys/mman.h>
00021 #include <fcntl.h>
00022 #include <errno.h>
00023 #include <dirent.h>
00024 #include <sys/utsname.h>
00025 #if !defined(OS_ARCH) && defined(HAVE_SYSINFO) && defined(HAVE_SYS_SYSTEMINFO_H)
00026 #include <sys/systeminfo.h>
00027 #endif
00028 
00029 #include "iiimcfint.h"
00030 
00031 #define NODE_KEY       "node="
00032 #define NODE_KEY_LEN   (5)
00033 #define SERVICE_KEY    "service="
00034 #define SERVICE_KEY_LEN       (8)
00035 #define CERT_FILE         "tls_cert="
00036 #define CERT_FILE_LEN     (9)
00037 #define CERT_KEY_FILE     "tls_key="
00038 #define CERT_KEY_FILE_LEN (8)
00039 #define CERT_CA_FILE      "tls_cafile="
00040 #define CERT_CA_FILE_LEN  (11)
00041 #define CERT_CA_PATH      "tls_capath="
00042 #define CERT_CA_PATH_LEN  (11)
00043 #define USE_TLS           "use_tls="
00044 #define USE_TLS_LEN       (8)
00045 
00046 #define SERVER_FILE         ".iiim/server"
00047 #define SERVER_FILE_LEN            (12)
00048 
00049 #define SERVER_COMPAT_FILE  ".iiimp"
00050 #define SERVER_COMPAT_FILE_LEN     (6)
00051 #define SERVER_COMPAT_KEY   "iiimp.server=iiimp://"
00052 #define SERVER_COMPAT_KEY_LEN      (21)
00053 
00054 #define CONFIG_DIR_BASE            ".iiim"
00055 #define CONFIG_DIR_AUTH            ".iiim/auth"
00056 #define CONFIG_FILE_PASSWD  ".iiim/auth/passwd"
00057 #define PASSWORD_FILE_LEN   (17)
00058 #define AUTH_PASSWORD_LEN   (32)
00059 #define HOME_ENV            "HOME"
00060 #define IIIM_SERVER_ENV            "IIIM_SERVER"
00061 
00062 #define CLIENT_TYPE         "generic IIIMP client"
00063 
00064 
00065 #define POSITION_HEAD(p, n) \
00066        for (; 0 < n; --(n), (p)++) { \
00067               if ((' ' != *(p)) && ('\t' != *(p)) && \
00068                   ('\r' != *(p)) && ('\n' != *(p))) { \
00069                      break; \
00070               } \
00071        } \
00072        if ((0 < (n)) && ((',' == *(p)) || (';' == *(p)))) { \
00073               --(n); \
00074               (p)++; \
00075        } \
00076        for (; 0 < n; --(n), (p)++) { \
00077               if ((' ' != *(p)) && ('\t' != *(p)) && \
00078                   ('\r' != *(p)) && ('\n' != *(p))) { \
00079                      break; \
00080               } \
00081        }
00082 
00083 #define POSITION_TAIL(p, n) \
00084        for (; 0 < n; --(n), (p)++) { \
00085               if ((',' == *(p)) || (';' == *(p)) || \
00086                   (' ' == *(p)) || ('\t' == *(p)) || \
00087                   ('\r' == *(p)) || ('\n' == *(p))) { \
00088                      break; \
00089               } \
00090        }
00091 
00092 #define POSITION_TAIL_COMPAT(p, n) \
00093        for (; 0 < n; --(n), (p)++) { \
00094               if ((':' == *(p)) || ('\r' == *(p)) || ('\n' == *(p))) { \
00095                      break; \
00096               } \
00097        }
00098 
00099 
00100 static IIIMF_status
00101 get_param(
00102     const char **    buf,
00103     size_t *         nbyte,
00104     const char *     key,
00105     size_t           key_len,
00106     char **          param_ret
00107 )
00108 {
00109     const char *     b;
00110     const char *     p;
00111     size_t           n;
00112     size_t           m;
00113     size_t           len;
00114     char *           param;
00115 
00116     b = *buf;
00117     n = *nbyte;
00118 
00119     if (n < key_len) return IIIMF_STATUS_CONFIG;
00120 
00121     if (0 != strncasecmp(b, key, key_len)) {
00122        return IIIMF_STATUS_CONFIG;
00123     }
00124 
00125     b += key_len;
00126     n -= key_len;
00127     p = b;
00128     m = n;
00129 
00130     POSITION_TAIL(b, n);
00131 
00132     len = (m - n);
00133 
00134     param = (char *)malloc(len + 1);
00135     if (NULL == param) return IIIMF_STATUS_MALLOC;
00136 
00137     (void)memcpy(param, p, len);
00138     *(param + len) = '\0';
00139 
00140     *buf = b;
00141     *nbyte = n;
00142     *param_ret = param;
00143 
00144     return IIIMF_STATUS_SUCCESS;
00145 }
00146 
00147 
00148 static IIIMF_status
00149 get_param_compat(
00150     const char **    buf,
00151     size_t *         nbyte,
00152     const char *     key,
00153     size_t           key_len,
00154     char **          param_ret
00155 )
00156 {
00157     const char *     b;
00158     const char *     p;
00159     size_t           n;
00160     size_t           m;
00161     size_t           len;
00162     char *           param;
00163 
00164     b = *buf;
00165     n = *nbyte;
00166 
00167     if (n < key_len) return IIIMF_STATUS_CONFIG;
00168 
00169     if (0 != strncasecmp(b, key, key_len)) {
00170        return IIIMF_STATUS_CONFIG;
00171     }
00172 
00173     b += key_len;
00174     n -= key_len;
00175     p = b;
00176     m = n;
00177 
00178     POSITION_TAIL_COMPAT(b, n);
00179 
00180     len = (m - n);
00181 
00182     param = (char *)malloc(len + 1);
00183     if (NULL == param) return IIIMF_STATUS_MALLOC;
00184 
00185     (void)memcpy(param, p, len);
00186     *(param + len) = '\0';
00187 
00188     *buf = b;
00189     *nbyte = n;
00190     *param_ret = param;
00191 
00192     return IIIMF_STATUS_SUCCESS;
00193 }
00194 
00195 static void
00196 iiimcf_client_config_free(
00197     IIIMCF_client_conf *pconf
00198 )
00199 {
00200     IIIMCF_client_conf *pc;
00201     IIIMCF_client_conf *pc2;
00202 
00203     if (!pconf) return;
00204     for (pc = pconf; pc; ) {
00205         pc2 = pc->next;
00206         if(pc->server_node) free(pc->server_node);
00207         if(pc->service) free(pc->service);
00208         if(pc->cert_file) free(pc->cert_file);
00209         if(pc->cert_key) free(pc->cert_key);
00210         if(pc->ca_file) free(pc->ca_file);
00211         if(pc->ca_path) free(pc->ca_path);
00212         free(pc);
00213         pc = pc2;
00214     }
00215 }
00216 
00217 static IIIMCF_client_conf *
00218 iiimcf_client_config_new(
00219     char *node,
00220     char *service
00221 )
00222 {
00223     IIIMCF_client_conf *ret;
00224     ret = malloc(sizeof(*ret));
00225     if (!ret) return NULL;
00226     memset(ret, 0, sizeof(*ret));
00227 
00228     ret->server_node = node;
00229     ret->service = service;
00230     return ret;
00231 }
00232 
00233 static IIIMF_status
00234 iiimcf_client_file_server(
00235     IIIMCF_client_env *penv
00236 )
00237 {
00238     int                     fd;
00239     IIIMF_status     status;
00240     char *           server_file;
00241     size_t           server_file_len;
00242     size_t           home_dir_len;
00243     struct stat             st;
00244     int                     stat_ret;
00245     char *           pa;
00246     const char *     p;
00247     size_t           rest;
00248     IIIMCF_client_conf  *pconf = NULL;
00249     char *           node = NULL;
00250 
00251     if (!penv->home_dir) return IIIMF_STATUS_CONFIG;
00252 
00253     home_dir_len = strlen(penv->home_dir);
00254     server_file_len = (home_dir_len + 1 + SERVER_FILE_LEN);
00255 
00256     server_file = (char *)malloc(server_file_len + 1);
00257     if (NULL == server_file) {
00258        return IIIMF_STATUS_MALLOC;
00259     }
00260 
00261     (void)strcpy(server_file, penv->home_dir);
00262     *(server_file + home_dir_len) = '/';
00263     (void)strcpy(server_file + home_dir_len + 1, SERVER_FILE);
00264 
00265     fd = open(server_file, O_RDONLY, 0);
00266     free(server_file);
00267     if (fd < 0) return IIIMF_STATUS_CONFIG;
00268 
00269     stat_ret = fstat(fd, &st);
00270     if (stat_ret < 0) {
00271        return IIIMF_STATUS_CONFIG;
00272     }
00273 
00274     pa = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
00275     (void)close(fd);
00276     if (NULL == pa) return IIIMF_STATUS_CONFIG;
00277 
00278     p = pa;
00279     rest = st.st_size;
00280 
00281     /* create client pconfig */
00282     for (; rest > 0; ) {
00283         POSITION_HEAD(p, rest);
00284         if (rest == 0) break;
00285 
00286         if (!strncasecmp(p, NODE_KEY, NODE_KEY_LEN)) {
00287             IIIMCF_client_conf *pconf_next;
00288             status = get_param(&p, &rest, NODE_KEY, NODE_KEY_LEN, &node);
00289             if (IIIMF_STATUS_SUCCESS != status) {
00290                 goto error;
00291             }
00292             if (!penv->pconf) {
00293                 /* if penv->pconf is not yet initialized, the first one */
00294                 penv->pconf = iiimcf_client_config_new(node, NULL);
00295                 if (!penv->pconf) {
00296                     free(node);
00297                     goto error;
00298                 }
00299                 pconf = penv->pconf;
00300             } else {
00301                 /* otherwise, create new pconfig and link to penv->pconf */
00302                 pconf_next = iiimcf_client_config_new(node, NULL);
00303                 if (!pconf_next) {
00304                     free(node);
00305                     goto error;
00306                 }
00307                 pconf->next = pconf_next;
00308                 pconf = pconf_next;
00309             }
00310         } else if (!strncasecmp(p, SERVICE_KEY, SERVICE_KEY_LEN)) {
00311             if (!pconf) goto error;
00312             status = get_param(&p, &rest, SERVICE_KEY, SERVICE_KEY_LEN, &pconf->service);
00313             if (IIIMF_STATUS_SUCCESS != status) {
00314                goto error;
00315             }
00316         } else if (!strncasecmp(p, CERT_FILE, CERT_FILE_LEN)) {
00317             if (!pconf) goto error;
00318             status = get_param(&p, &rest, CERT_FILE, CERT_FILE_LEN, &pconf->cert_file);
00319             if (IIIMF_STATUS_SUCCESS != status) {
00320                goto error;
00321             }
00322         } else if (!strncasecmp(p, CERT_KEY_FILE, CERT_KEY_FILE_LEN)) {
00323             if (!pconf) goto error;
00324             status = get_param(&p, &rest, CERT_FILE, CERT_FILE_LEN, &pconf->cert_key);
00325             if (IIIMF_STATUS_SUCCESS != status) {
00326                goto error;
00327             }
00328         } else if (!strncasecmp(p, CERT_CA_FILE, CERT_CA_FILE_LEN)) {
00329             if (!pconf) goto error;
00330             status = get_param(&p, &rest, CERT_CA_FILE, CERT_CA_FILE_LEN, &pconf->ca_file);
00331             if (IIIMF_STATUS_SUCCESS != status) {
00332                goto error;
00333             }
00334         } else if (!strncasecmp(p, CERT_CA_PATH, CERT_CA_PATH_LEN)) {
00335             if (!pconf) goto error;
00336             status = get_param(&p, &rest, CERT_CA_PATH, CERT_CA_PATH_LEN, &pconf->ca_path);
00337             if (IIIMF_STATUS_SUCCESS != status) {
00338                goto error;
00339             }
00340         } else if (!strncasecmp(p, USE_TLS, USE_TLS_LEN)) {
00341             char *use_tls;
00342             if (!pconf) goto error;
00343             status = get_param(&p, &rest, USE_TLS, USE_TLS_LEN, &use_tls);
00344             if (IIIMF_STATUS_SUCCESS != status) {
00345                goto error;
00346             }
00347             if (!strcasecmp(use_tls, "yes")) {
00348                 pconf->use_tls = 1;
00349             }
00350             free(use_tls);
00351         } else {
00352             POSITION_TAIL(p, rest);
00353         }
00354     }
00355 
00356     (void)munmap(pa, st.st_size);
00357     return IIIMF_STATUS_SUCCESS;
00358 
00359 error:
00360 
00361     iiimcf_client_config_free(penv->pconf);
00362     penv->pconf = NULL;
00363     (void)munmap(pa, st.st_size);
00364     return IIIMF_STATUS_CONFIG;
00365 }
00366 
00367 
00368 static IIIMF_status
00369 iiimcf_client_file_compat_server(
00370     IIIMCF_client_env *penv
00371 )
00372 {
00373     int                     fd;
00374     IIIMF_status     status;
00375     char *           server_file;
00376     size_t           server_file_len;
00377     size_t           home_dir_len;
00378     struct stat             st;
00379     int                     stat_ret;
00380     char *           pa;
00381     const char *     p;
00382     size_t           rest;
00383     char *           node = NULL;
00384     char *           service;
00385 
00386     if (!penv->home_dir) return IIIMF_STATUS_CONFIG;
00387     home_dir_len = strlen(penv->home_dir);
00388     server_file_len = (home_dir_len + 1 + SERVER_COMPAT_FILE_LEN);
00389 
00390     server_file = (char *)malloc(server_file_len + 1);
00391     if (NULL == server_file) {
00392        return IIIMF_STATUS_MALLOC;
00393     }
00394 
00395     (void)strcpy(server_file, penv->home_dir);
00396     *(server_file + home_dir_len) = '/';
00397     (void)strcpy(server_file + home_dir_len + 1, SERVER_COMPAT_FILE);
00398 
00399     fd = open(server_file, O_RDONLY, 0);
00400     free(server_file);
00401     if (fd < 0) return IIIMF_STATUS_CONFIG;
00402     stat_ret = fstat(fd, &st);
00403     if (stat_ret < 0) {
00404        return IIIMF_STATUS_CONFIG;
00405     }
00406 
00407     pa = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
00408     (void)close(fd);
00409     if (NULL == pa) return IIIMF_STATUS_CONFIG;
00410 
00411     p = pa;
00412     rest = st.st_size;
00413 
00414     while (0 < rest) {
00415        for (; 0 < rest; --rest, p++) {
00416            if (('\r' == *p) || ('\n' == *p)) {
00417               p += 1;
00418               rest -= 1;
00419               break;
00420            }
00421        }
00422        if (rest < SERVER_COMPAT_KEY_LEN) break;
00423 
00424        status = get_param_compat(&p, &rest,
00425                               SERVER_COMPAT_KEY,
00426                               SERVER_COMPAT_KEY_LEN,
00427                               &node);
00428        if (IIIMF_STATUS_SUCCESS == status) {
00429            p += 1;
00430            rest -= 1;
00431            break;
00432        }
00433     }
00434     if (!node) {
00435        return IIIMF_STATUS_CONFIG;
00436     }
00437 
00438     status = get_param_compat(&p, &rest, "", 0, &service);
00439 
00440     (void)munmap(pa, st.st_size);
00441 
00442     if ('\0' == *service) {
00443        free(service);
00444        service = NULL;
00445     }
00446 
00447     if (IIIMF_STATUS_SUCCESS == status) {
00448         penv->pconf = iiimcf_client_config_new(node, service);
00449     }
00450 
00451     return status;
00452 }
00453 
00454 static IIIMF_status
00455 iiimcf_client_environ_server(
00456     IIIMCF_client_env *penv
00457 )
00458 {
00459     IIIMF_status     status;
00460     const char *     p;
00461     size_t           rest;
00462     char *           node;
00463     char *           service;
00464 
00465     p = getenv(IIIM_SERVER_ENV);
00466     if (NULL == p) return IIIMF_STATUS_FAIL;
00467 
00468     rest = strlen(p);
00469 
00470     status = get_param(&p, &rest, "", 0, &node);
00471     if (IIIMF_STATUS_SUCCESS != status) {
00472        return status;
00473     }
00474 
00475     POSITION_HEAD(p, rest);
00476 
00477     status = get_param(&p, &rest, "", 0, &service);
00478 
00479     penv->pconf = iiimcf_client_config_new(node, service);
00480 
00481     return IIIMF_STATUS_SUCCESS;
00482 }
00483 
00484 static void
00485 auth_password_generate(
00486     char * password,
00487     size_t length
00488 )
00489 {
00490     int                     fd;
00491     unsigned int     seed;
00492     int                     c;
00493     int                     i;
00494     int                     r;
00495     unsigned int *   p;
00496     size_t           n;
00497     char *           c62;
00498 
00499     *(password + length) = '\0';
00500 
00501     c62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
00502     fd = open("/dev/random", O_RDONLY, 0);
00503     if (0 <= fd) {
00504        r = 0;
00505        n = ((sizeof (unsigned int)) * length);
00506        p = (unsigned int * )malloc(n);
00507        if (NULL != p) {
00508            r = read(fd, p, n);
00509        }
00510        (void)close(fd);
00511        if (r == length) {
00512            for (i = 0; i < length; i++) {
00513               *(password + i) = *(c62 + (*(p + i) % 62));
00514            }
00515            free(p);
00516            return;
00517        }
00518        free(p);
00519     }
00520 
00521     seed = (time(NULL) + getpid());
00522     srand(seed);
00523     for (i = 0; i < length; i++) {
00524        c = rand();
00525        *(password + i) = *(c62 + (c % 62));
00526     }
00527 
00528     return;
00529 }
00530 
00531 static int
00532 auth_password_file_init(
00533     char * password_file,
00534     size_t home_dir_len
00535 )
00536 {
00537     int              fd;
00538     char      pwd_buf[AUTH_PASSWORD_LEN + 1];
00539     struct stat      st;
00540     ssize_t   len;
00541 
00542     /* ${HOME}/.iiim */
00543     (void)strcpy(password_file + home_dir_len, CONFIG_DIR_BASE);
00544     if (0 != stat(password_file, &st)) {
00545        if (ENOENT != errno) return -1;
00546        if (0 != mkdir(password_file, 0777)) return -1;
00547     }
00548 
00549     /* ${HOME}/.iiim/auth */
00550     (void)strcpy(password_file + home_dir_len, CONFIG_DIR_AUTH);
00551     if (0 != stat(password_file, &st)) {
00552        if (ENOENT != errno) return -1;
00553        if (0 != mkdir(password_file, 0700)) return -1;
00554     }
00555 
00556     /* ${HOME}/.iiim/auth/password */
00557     (void)strcpy(password_file + home_dir_len, CONFIG_FILE_PASSWD);
00558     fd = open(password_file, O_CREAT | O_WRONLY, 0600);
00559     if (-1 == fd) return -1;
00560 
00561     auth_password_generate(pwd_buf, AUTH_PASSWORD_LEN);
00562 
00563     len = write(fd, pwd_buf, AUTH_PASSWORD_LEN + 1);
00564     (void)close(fd);
00565 
00566     if ((AUTH_PASSWORD_LEN + 1) == len) {
00567        return 0;
00568     } else {
00569        return -1;
00570     }
00571 }
00572 
00573 
00574 static int
00575 auth_password_file_open(
00576     const char * home_dir
00577 )
00578 {
00579     char *    password_file;
00580     char *    home_env;
00581     int              home_dir_len;
00582     int              len;
00583     struct stat      st;
00584     int              fd;
00585 
00586     password_file = NULL;
00587 
00588     if (NULL == home_dir) {
00589        home_env = getenv("HOME");
00590        if (NULL != home_env) {
00591            home_dir = home_env;
00592        }
00593        if (NULL == home_dir) {
00594            return -1;
00595        }
00596     }
00597 
00598     home_dir_len = strlen(home_dir);
00599     len = (home_dir_len + 1 + PASSWORD_FILE_LEN);
00600 
00601     password_file = malloc(len + 1);
00602     if (NULL == password_file) {
00603        return -1;
00604     }
00605 
00606     (void)strcpy(password_file, home_dir);
00607     *(password_file + home_dir_len) = '/';
00608     home_dir_len += 1;
00609     (void)strcpy(password_file + home_dir_len, CONFIG_FILE_PASSWD);
00610 
00611     if (0 != stat(password_file, &st)) {
00612        (void)auth_password_file_init(password_file, home_dir_len);
00613     }
00614 
00615     fd = open(password_file, O_RDONLY, 0);
00616     free(password_file);
00617 
00618     return fd;
00619 }
00620 
00621 static IIIMF_status
00622 iiimcf_client_auth_password(
00623     IIIMCF_client_env *penv
00624 )
00625 {
00626     char *    password;
00627 
00628     if (penv->password) return IIIMF_STATUS_SUCCESS;
00629 
00630 #if 0
00631     int              fd;
00632     int              len;
00633     int              i;
00634     char      pwd_buf[AUTH_PASSWORD_LEN + 1];
00635 
00636     password = NULL;
00637     fd = -1;
00638 
00639     if (!penv->home_dir) return IIIMF_STATUS_CONFIG;
00640     fd = auth_password_file_open(penv->home_dir);
00641     if (-1 == fd) return IIIMF_STATUS_CONFIG;
00642 
00643     len = read(fd, pwd_buf, AUTH_PASSWORD_LEN);
00644     (void)close(fd);
00645 
00646     if (AUTH_PASSWORD_LEN != len) return IIIMF_STATUS_CONFIG;
00647 
00648     for (i = 0; i < AUTH_PASSWORD_LEN; i++) {
00649        if (0 == isalnum(pwd_buf[i])) {
00650            return IIIMF_STATUS_CONFIG;
00651        }
00652     }
00653     if (AUTH_PASSWORD_LEN != i) {
00654        return IIIMF_STATUS_CONFIG;
00655     }
00656 
00657     password = malloc(AUTH_PASSWORD_LEN + 1);
00658     if (NULL == password) return IIIMF_STATUS_MALLOC;
00659     (void)memcpy(password, pwd_buf, AUTH_PASSWORD_LEN);
00660     *(password + AUTH_PASSWORD_LEN) = '\0';
00661 
00662     penv->password = password;
00663 
00664 #endif
00665     return IIIMF_STATUS_SUCCESS;
00666 }
00667 
00668 static IIIMF_status
00669 iiimcf_client_os_arch(
00670     IIIMCF_client_env *penv
00671 )
00672 {
00673 
00674 #if defined(OS_ARCH)
00675     penv->os_arch = strdup(OS_ARCH);
00676 #else /* !OS_ARCH */
00677 #if defined(HAVE_SYSINFO) && defined(SI_ARCHITECTURE)
00678     {
00679         char arch[16];
00680        int ret;
00681        ret = sysinfo(SI_ARCHITECTURE, arch, sizeof (arch));
00682        if (-1 == ret) {
00683            penv->os_arch = NULL;
00684        } else if ((0 == strcmp(arch, "sparc")) ||
00685                  (0 == strcmp(arch, "ppc"))) {
00686            penv->os_arch = strdup(arch);
00687        } else if (0 == strcmp(arch, "i386")) {
00688            penv->os_arch = strdup("x86");
00689        } else {
00690            penv->os_arch = strdup("Unknown");
00691        }
00692     }
00693 #else /* !HAVE_SYSINFO || !SI_ARCHITECTURE */
00694     penv->os_arch = strdup("Unknown");
00695 #endif /* !HAVE_SYSINFO || !SI_ARCHITECTURE */
00696 #endif /* !OS_ARCH */
00697     if (!penv->os_arch)
00698        return IIIMF_STATUS_MALLOC;
00699 
00700     return IIIMF_STATUS_SUCCESS;
00701 }
00702 
00703 
00704 static IIIMF_status
00705 dir_valid(const char * path_name, uid_t euid)
00706 {
00707        struct stat   st;
00708 
00709 #if !defined(S_IAMB)
00710 #define       S_IAMB 0x1FF
00711 #endif /* !S_IAMB */
00712 
00713        if ((0 == lstat(path_name, &st)) &&
00714            (0 != S_ISDIR(st.st_mode)) &&
00715            (euid == st.st_uid) &&
00716            ((S_IAMB & st.st_mode) == S_IRWXU)) {
00717            return IIIMF_STATUS_SUCCESS;
00718        } else {
00719            return IIIMF_STATUS_FAIL;
00720        }
00721 }
00722 
00723 
00724 static IIIMF_status
00725 iiimcf_alternate_unix_domain_socket_file_dir(
00726     IIIMCF_client_env *     penv,
00727     char **          path_name
00728 )
00729 {
00730     DIR *            dir;
00731     struct dirent *  dirent;
00732     char *           base_name;
00733     size_t           base_name_len;
00734     char *           dir_name;
00735     size_t           dir_name_len;
00736     IIIMF_status     found;
00737     uid_t            euid;
00738 
00739     dir = opendir("/tmp");
00740     if (NULL == dir) return IIIMF_STATUS_FAIL;
00741 
00742     base_name_len = (strlen(".iiimp-unix-") + strlen(penv->user_name) + 1);
00743     base_name = (char *)malloc(base_name_len + 1);
00744     if (NULL == base_name) {
00745        closedir(dir);
00746        return IIIMF_STATUS_MALLOC;
00747     }
00748     snprintf(base_name, base_name_len + 1, ".iiimp-unix-%s-", penv->user_name);
00749 
00750     euid = geteuid();
00751 
00752     found = IIIMF_STATUS_FAIL;
00753     while (NULL != (dirent = readdir(dir))) {
00754        if (0 != strncmp(dirent->d_name, base_name, base_name_len)) {
00755            continue;
00756        }
00757 
00758        dir_name_len = (strlen("/tmp") + 1 + strlen(dirent->d_name) + 1);
00759        dir_name = (char *)malloc(dir_name_len);
00760        if (NULL == dir_name) {
00761            found = IIIMF_STATUS_MALLOC;
00762            break;
00763        }
00764        snprintf(dir_name, dir_name_len, "/tmp/%s", dirent->d_name);
00765        found = dir_valid(dir_name, euid);
00766 
00767        if (IIIMF_STATUS_SUCCESS == found) {
00768            (*path_name) = dir_name;
00769            break;
00770        }
00771 
00772        free(dir_name);
00773     }
00774 
00775     free(base_name);
00776     closedir(dir);
00777 
00778     return found;
00779 }
00780 
00781 
00782 IIIMF_status
00783 iiimcf_create_client_env(
00784     IIIMCF_attr attr,
00785     IIIMCF_client_env **ppenv
00786 )
00787 {
00788     IIIMCF_client_env *penv;
00789     IIIMCF_client_conf *pconf;
00790     IIIMF_status st;
00791     const char *server_node, *service, *user_name, *password;
00792     const char *clientname, *x_display_name, *x_server_vendor;
00793 
00794     server_node = service = user_name = password = NULL;
00795     clientname = x_display_name = x_server_vendor = NULL;
00796 
00797     penv = (IIIMCF_client_env *)malloc(sizeof (IIIMCF_client_env));
00798     if (!penv) return IIIMF_STATUS_MALLOC;
00799     memset(penv, 0, sizeof(*penv));
00800 
00801     st = iiimcf_attr_get_string_value(attr,
00802                                   IIIMCF_ATTR_SERVER_ADDRESS,
00803                                   &server_node);
00804 
00805     if (st != IIIMF_STATUS_SUCCESS && st != IIIMF_STATUS_NO_ATTR_VALUE) goto error;
00806 
00807     st = iiimcf_attr_get_string_value(attr,
00808                                   IIIMCF_ATTR_SERVER_SERVICE,
00809                                   &service);
00810     if (st != IIIMF_STATUS_SUCCESS && st != IIIMF_STATUS_NO_ATTR_VALUE) goto error;
00811 
00812     if (server_node || service) {
00813         penv->pconf = iiimcf_client_config_new(server_node ? strdup(server_node) : NULL,
00814                                               service ?  strdup(service) : NULL);
00815         if (!penv->pconf) goto memory_error;
00816     }
00817 
00818 
00819     st = iiimcf_attr_get_string_value(attr,
00820                                   IIIMCF_ATTR_USERNAME,
00821                                   &user_name);
00822     if (st == IIIMF_STATUS_SUCCESS) {
00823        penv->user_name = strdup(user_name);
00824        if (!penv->user_name) goto memory_error;
00825     } else if (st != IIIMF_STATUS_NO_ATTR_VALUE) {
00826        goto error;
00827     }
00828     {
00829        struct passwd *pwd;
00830        /* TODO!  Use penv->user_name to check the
00831           home directory. */
00832        if ((pwd = getpwuid(geteuid()))) {
00833            if (!penv->user_name)
00834               penv->user_name = strdup(pwd->pw_name);
00835            if (!penv->user_name) goto memory_error;
00836            penv->home_dir = strdup(pwd->pw_dir);
00837            if (!penv->home_dir) goto memory_error;
00838        }
00839     }
00840     /* We still fail to get user_name, set "Unknown" with force.  */
00841     if (!penv->user_name) {
00842        penv->user_name = strdup("Unknown");
00843        if (!penv->user_name) goto memory_error;
00844     }
00845 
00846     st = iiimcf_attr_get_string_value(attr,
00847                                   IIIMCF_ATTR_PASSWORD,
00848                                   &password);
00849     if (st == IIIMF_STATUS_SUCCESS) {
00850        penv->password = strdup(password);
00851        if (!penv->password) goto memory_error;
00852     } else if (st == IIIMF_STATUS_NO_ATTR_VALUE) {
00853        st = iiimcf_client_auth_password(penv);
00854        if ((st != IIIMF_STATUS_SUCCESS)
00855            && (st != IIIMF_STATUS_CONFIG))
00856            goto error;
00857     } else {
00858        goto error;
00859     }
00860 
00861     if (!server_node && !service) {
00862        st = iiimcf_client_environ_server(penv);
00863        if (st != IIIMF_STATUS_SUCCESS) {
00864            st = iiimcf_client_file_server(penv);
00865            if (st != IIIMF_STATUS_SUCCESS) {
00866               st = iiimcf_client_file_compat_server(penv);
00867            }
00868        }
00869     }
00870     if (!penv->pconf) {
00871         /* 
00872          * we don't have any pconfiguration.
00873          * prepare default one.
00874          */
00875         int node_len;
00876         char *tmp_node;
00877 
00878         /* 
00879          * first try to /tmp/.iiimp-unix-${USERNAME}/
00880          */
00881        node_len = strlen("/tmp/.iiimp-unix-") + strlen(penv->user_name);
00882         tmp_node = malloc(node_len + 1);
00883         if (!tmp_node) goto memory_error;
00884         snprintf(tmp_node, node_len + 1, "/tmp/.iiimp-unix-%s", penv->user_name);
00885         tmp_node[node_len] = '\0';
00886 
00887        if (IIIMF_STATUS_SUCCESS != dir_valid(tmp_node, geteuid())) {
00888            /* 
00889             * try /tmp/.iiimp-unix-${USERNAME}-xxxxxxxx/
00890             */
00891            free(tmp_node);
00892            tmp_node = NULL;
00893            st = iiimcf_alternate_unix_domain_socket_file_dir(penv, &tmp_node);
00894        }
00895 
00896        if (NULL != tmp_node) {
00897            penv->pconf = iiimcf_client_config_new(tmp_node, NULL);
00898            if (!penv->pconf) {
00899               free(tmp_node);
00900               goto memory_error;
00901            }
00902        }
00903 
00904         /* 
00905          * second try to $SOCKETDIR/.iiimp-unix/
00906          */
00907         tmp_node = strdup(SOCKETDIR "/.iiimp-unix");
00908         if (!tmp_node) goto memory_error;
00909        pconf = iiimcf_client_config_new(tmp_node, NULL);
00910         if (NULL == pconf) {
00911             free(tmp_node);
00912             goto memory_error;
00913         }
00914 
00915        if (NULL == penv->pconf) {
00916            penv->pconf = pconf;
00917        } else {
00918            penv->pconf->next = pconf;
00919        }
00920     }
00921 
00922     st = iiimcf_attr_get_string_value(attr,
00923                                   IIIMCF_ATTR_CLIENT_TYPE,
00924                                   &clientname);
00925     if (st == IIIMF_STATUS_SUCCESS) {
00926        penv->type = strdup(clientname);
00927     } else if (st == IIIMF_STATUS_NO_ATTR_VALUE) {
00928        penv->type = strdup(CLIENT_TYPE);
00929     } else {
00930        goto error;
00931     }
00932     if (!penv->type) goto memory_error;
00933 
00934     st = iiimcf_attr_get_string_value(attr,
00935                                   IIIMCF_ATTR_CLIENT_X_DISPLAY_NAME,
00936                                   &x_display_name);
00937     if (st == IIIMF_STATUS_SUCCESS) {
00938        penv->X_display_name = strdup(x_display_name);
00939        if (!penv->X_display_name) goto memory_error;
00940     } else if (st != IIIMF_STATUS_NO_ATTR_VALUE) {
00941        goto error;
00942     }
00943 
00944     st = iiimcf_attr_get_string_value(attr,
00945                                   IIIMCF_ATTR_CLIENT_X_SERVER_VENDOR,
00946                                   &x_server_vendor);
00947     if (st == IIIMF_STATUS_SUCCESS) {
00948        penv->X_server_vendor = strdup(x_server_vendor);
00949        if (!penv->X_server_vendor) goto memory_error;
00950     } else if (st != IIIMF_STATUS_NO_ATTR_VALUE) {
00951        goto error;
00952     }
00953 
00954     {
00955        struct utsname name;
00956        if (-1 != uname(&name)) {
00957            penv->node = strdup(name.nodename);
00958            if (!penv->node) goto memory_error;
00959            penv->os_name = strdup(name.sysname);
00960            if (!penv->os_name) goto memory_error;
00961            penv->os_version = strdup(name.release);
00962            if (!penv->os_version) goto memory_error;
00963        }
00964     }
00965 
00966     st = iiimcf_client_os_arch(penv);
00967     if ((st != IIIMF_STATUS_SUCCESS)
00968        && (st != IIIMF_STATUS_CONFIG))
00969        goto error;
00970 
00971     *ppenv = penv;
00972 
00973     return IIIMF_STATUS_SUCCESS;
00974 
00975 memory_error:
00976     st = IIIMF_STATUS_MALLOC;
00977 error:
00978     iiimcf_delete_client_env(penv);
00979     return st;
00980 }
00981 
00982 IIIMF_status
00983 iiimcf_delete_client_env(
00984     IIIMCF_client_env *penv
00985 )
00986 {
00987     if (penv->user_name) free(penv->user_name);
00988     if (penv->password) free(penv->password);
00989     if (penv->home_dir) free(penv->home_dir);
00990     if (penv->node) free(penv->node);
00991     if (penv->type) free(penv->type);
00992     if (penv->os_name) free(penv->os_name);
00993     if (penv->os_arch) free(penv->os_arch);
00994     if (penv->os_version) free(penv->os_version);
00995     if (penv->X_display_name) free(penv->X_display_name);
00996     if (penv->X_server_vendor) free(penv->X_server_vendor);
00997     if (penv->pconf)  iiimcf_client_config_free(penv->pconf);
00998 
00999     free(penv);
01000     return IIIMF_STATUS_SUCCESS;
01001 }
01002 
01003 IIIMF_status
01004 iiimcf_create_im_connect_message(
01005     IIIMCF_handle_rec *ph,
01006     IIIMP_message **ppmes
01007 )
01008 {
01009     int len;
01010     char *user;
01011     IIIMF_status st;
01012     IIIMP_message *pmes;
01013     IIIMP_string *pim_user;
01014     IIIMCF_client_env *penv = ph->penv;
01015 
01016     len = strlen(penv->user_name);
01017     if (penv->node) len += strlen(penv->node);
01018     if (penv->X_display_name) len += strlen(penv->X_display_name);
01019     else len += 4;
01020     if (penv->password) len += strlen(penv->password);
01021     user = (char*) malloc(sizeof(char) * (len + 1 + 1 + 1)); /* for @, #, and \0. */
01022     if (!user) return IIIMF_STATUS_MALLOC;
01023     strcpy(user, penv->user_name);
01024     if (penv->node) {
01025        strcat(user, "@");
01026        strcat(user, penv->node);
01027         /* printf("penv->X_display_name [%s]\n", penv->X_display_name); */
01028         if (penv->X_display_name) {
01029          strcat(user, penv->X_display_name);
01030         } else {
01031          penv->X_display_name = strdup(":0.0");
01032          strcat(user, ":0.0");
01033         }
01034     }
01035     if (penv->password) {
01036        strcat(user, "#");
01037        strcat(user, penv->password);
01038     }
01039     st = iiimf_data_string_ascii_new(ph->data_s, user, &pim_user);
01040     free(user);
01041     if (st != IIIMF_STATUS_SUCCESS) return st;
01042     pmes = iiimp_connect_new(ph->data_s, pim_user, NULL);
01043     if (!pmes) {
01044        iiimp_string_delete(ph->data_s, pim_user);
01045        return IIIMF_STATUS_MALLOC;
01046     }
01047 
01048     *ppmes = pmes;
01049 
01050     return IIIMF_STATUS_SUCCESS;
01051 }
01052 
01053 IIIMF_status
01054 iiimcf_create_client_descriptor_message(
01055     IIIMCF_handle_rec *ph,
01056     IIIMP_message **ppmes
01057 )
01058 {
01059     IIIMF_status st;
01060     IIIMCF_client_env *penv = ph->penv;
01061     IIIMP_message *pmes;
01062     IIIMP_imattribute *pimattr;
01063     IIIMP_client_descriptor *cdesc;
01064     IIIMP_string *type, *os_name, *os_arch, *os_ver;
01065     IIIMP_string *X_display_name, *X_server_vendor;
01066 
01067     pmes = NULL;
01068     pimattr = NULL;
01069     cdesc = NULL;
01070     type = os_name = os_arch = os_ver = NULL;
01071     X_display_name = X_server_vendor = NULL;
01072 
01073     st = iiimf_data_string_ascii_new(ph->data_s, penv->type, &type);
01074     if (st != IIIMF_STATUS_SUCCESS) goto error;
01075     st = iiimf_data_string_ascii_new(ph->data_s, penv->os_name, &os_name);
01076     if (st != IIIMF_STATUS_SUCCESS) goto error;
01077     st = iiimf_data_string_ascii_new(ph->data_s, penv->os_arch, &os_arch);
01078     if (st != IIIMF_STATUS_SUCCESS) goto error;
01079     st = iiimf_data_string_ascii_new(ph->data_s, penv->os_version, &os_ver);
01080     if (st != IIIMF_STATUS_SUCCESS) goto error;
01081 
01082     if (penv->X_display_name) {
01083        st = iiimf_data_string_ascii_new(ph->data_s,
01084                                     penv->X_display_name,
01085                                     &X_display_name);
01086        if (st != IIIMF_STATUS_SUCCESS) goto error;
01087     }
01088     if (penv->X_server_vendor) {
01089        st = iiimf_data_string_ascii_new(ph->data_s,
01090                                     penv->X_server_vendor,
01091                                     &X_server_vendor);
01092        if (st != IIIMF_STATUS_SUCCESS) goto error;
01093     }
01094 
01095     cdesc = iiimp_client_descriptor_new(ph->data_s,
01096                                    type, os_name, os_arch, os_ver,
01097                                    X_display_name, X_server_vendor);
01098     if (!cdesc) goto error;
01099 
01100     pimattr = iiimp_imattribute_client_descriptor_new(ph->data_s,
01101                                                 IIIMP_IMATTRIBUTE_CLIENT_DESCRIPTOR,
01102                                                 0, cdesc);
01103     if (!pimattr) goto error;
01104 
01105     pmes = iiimp_setimvalues_new(ph->data_s, ph->im_id, pimattr);
01106     if (!pmes) goto error;
01107 
01108     *ppmes = pmes;
01109 
01110     return IIIMF_STATUS_SUCCESS;
01111 
01112 error:
01113     if (type) iiimp_string_delete(ph->data_s, type);
01114     if (os_name) iiimp_string_delete(ph->data_s, os_name);
01115     if (os_arch) iiimp_string_delete(ph->data_s, os_arch);
01116     if (os_ver) iiimp_string_delete(ph->data_s, os_ver);
01117     if (X_display_name) iiimp_string_delete(ph->data_s, X_display_name);
01118     if (X_server_vendor) iiimp_string_delete(ph->data_s, X_server_vendor);
01119     if (cdesc) iiimp_client_descriptor_delete(ph->data_s, cdesc);
01120     if (pimattr) iiimp_imattribute_delete(ph->data_s, pimattr);
01121 
01122     return IIIMF_STATUS_MALLOC;
01123 }
01124 
01125 /* Local Variables: */
01126 /* c-file-style: "iiim-project" */
01127 /* End: */