/*___INFO__MARK_BEGIN__*/ /************************************************************************* * * The Contents of this file are made available subject to the terms of * the Sun Industry Standards Source License Version 1.2 * * Sun Microsystems Inc., March, 2001 * * * Sun Industry Standards Source License Version 1.2 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.2 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2001 by Sun Microsystems, Inc. * * All Rights Reserved. * ************************************************************************/ /*___INFO__MARK_END__*/ #include #include #include #define SGE_PASSWD_PROG_NAME "sgepasswd" #ifdef SECURE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uti/sge_arch.h" #include "uti/sge_log.h" #include "uti/sge_unistd.h" #include "uti/sge_uidgid.h" #include "uti/sge_profiling.h" #include "uti/sge_bootstrap.h" #include "uti/setup_path.h" #include "uti/sge_prog.h" #include "uti/sge_stdio.h" #include "uti/sge_string.h" #include "uti/sge_stdlib.h" #if defined(DEFINE_SGE_PASSWD_MAIN) #include "sgermon.h" #endif #include "sge_passwd.h" #include "msg_utilbin.h" #include "msg_gdilib.h" #if !defined(DEFINE_SGE_PASSWD_MAIN) #define DENTER(x,y) #define DPRINTF(x) #define DEXIT #endif static void (*shared_ssl_func__X509_free)(X509 *a); static void (*shared_ssl_func__EVP_PKEY_free)(EVP_PKEY *pkey); static void (*shared_ssl_func__ERR_print_errors_fp)(FILE *fp); unsigned long (*shared_ssl_func__ERR_get_error)(void); char* (*shared_ssl_func__ERR_error_string)(unsigned long e, char *buf); static int (*shared_ssl_func__EVP_PKEY_size)(EVP_PKEY *pkey); static const EVP_CIPHER* (*shared_ssl_func__EVP_rc4)(void); static int (*shared_ssl_func__EVP_OpenInit)(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char *ek, int ekl, unsigned char *iv, EVP_PKEY *priv); static int (*shared_ssl_func__EVP_DecryptUpdate)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl); static int (*shared_ssl_func__EVP_EncryptUpdate)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl); static int (*shared_ssl_func__EVP_SealFinal)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); static int (*shared_ssl_func__EVP_SealInit)(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char **ek, int *ekl, unsigned char *iv, EVP_PKEY **pubk, int npubk); static int (*shared_ssl_func__EVP_OpenFinal)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); static int (*shared_ssl_func__EVP_read_pw_string)(char *buf, int length, const char *prompt, int verify); static void (*shared_ssl_func__ERR_load_crypto_strings)(void); static EVP_PKEY* (*shared_ssl_func__X509_get_pubkey)(X509 *x); static char* (*shared_ssl_func__PEM_ASN1_read)(char *(*d2i)(),const char *name,FILE *fp,char **x, pem_password_cb *cb, void *u); EVP_PKEY* (*shared_ssl_func__d2i_AutoPrivateKey)(EVP_PKEY **a, unsigned char **pp, long length); static X509* (*shared_ssl_func__d2i_X509)(X509 **a, unsigned char **in, long len); static int (*shared_ssl_func__RAND_load_file)(const char *filename, long max_bytes); #define shared_ssl_func__EVP_OpenUpdate(a,b,c,d,e) shared_ssl_func__EVP_DecryptUpdate(a,b,c,d,e) #define shared_ssl_func__EVP_SealUpdate(a,b,c,d,e) shared_ssl_func__EVP_EncryptUpdate(a,b,c,d,e) #define shared_ssl_func__X509_extract_key(x) shared_ssl_func__X509_get_pubkey(x) #define shared_ssl_func__PEM_read_X509(fp,x,cb,u) (X509 *)shared_ssl_func__PEM_ASN1_read((char *(*)())shared_ssl_func__d2i_X509,PEM_STRING_X509,fp,(char **)x,cb,u) #define shared_ssl_func__PEM_read_PrivateKey(fp,x,cb,u) (EVP_PKEY *)shared_ssl_func__PEM_ASN1_read((char *(*)())shared_ssl_func__d2i_AutoPrivateKey,PEM_STRING_EVP_PKEY,fp,(char **)x,cb,u) #ifdef LOAD_OPENSSL static void* shared_ssl_lib = NULL; #endif int sge_init_shared_ssl_lib(void) { int ret; DENTER(TOP_LAYER, "sge_init_shared_ssl_lib"); #ifdef LOAD_OPENSSL if (shared_ssl_lib == NULL) { # if defined(DARWIN) # ifdef RTLD_NODELETE shared_ssl_lib = dlopen ("libcrypto.bundle", RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); # else shared_ssl_lib = dlopen ("libcrypto.bundle", RTLD_NOW | RTLD_GLOBAL ); # endif /* RTLD_NODELETE */ # elif defined(HP11) || defined(HP1164) # ifdef RTLD_NODELETE shared_ssl_lib = dlopen ("libcrypto.sl", RTLD_LAZY | RTLD_NODELETE); # else shared_ssl_lib = dlopen ("libcrypto.sl", RTLD_LAZY ); # endif /* RTLD_NODELETE */ # else # ifdef RTLD_NODELETE shared_ssl_lib = dlopen ("libcrypto.so", RTLD_LAZY | RTLD_NODELETE); # else shared_ssl_lib = dlopen ("libcrypto.so", RTLD_LAZY); # endif /* RTLD_NODELETE */ #endif if (shared_ssl_lib != NULL) { const char *func_name[] = { "X509_free", "EVP_PKEY_free", "ERR_print_errors_fp", "EVP_PKEY_size", "EVP_rc4", "EVP_OpenInit", "EVP_DecryptUpdate", "EVP_EncryptUpdate", "EVP_SealFinal", "EVP_SealInit", "EVP_OpenFinal", "EVP_read_pw_string", "ERR_load_crypto_strings", "X509_get_pubkey", "PEM_ASN1_read", "d2i_AutoPrivateKey", "d2i_X509", "RAND_load_file", "ERR_get_error", "ERR_error_string", NULL }; const void *func_ptr[] = { &shared_ssl_func__X509_free, &shared_ssl_func__EVP_PKEY_free, &shared_ssl_func__ERR_print_errors_fp, &shared_ssl_func__EVP_PKEY_size, &shared_ssl_func__EVP_rc4, &shared_ssl_func__EVP_OpenInit, &shared_ssl_func__EVP_DecryptUpdate, &shared_ssl_func__EVP_EncryptUpdate, &shared_ssl_func__EVP_SealFinal, &shared_ssl_func__EVP_SealInit, &shared_ssl_func__EVP_OpenFinal, &shared_ssl_func__EVP_read_pw_string, &shared_ssl_func__ERR_load_crypto_strings, &shared_ssl_func__X509_get_pubkey, &shared_ssl_func__PEM_ASN1_read, &shared_ssl_func__d2i_AutoPrivateKey, &shared_ssl_func__d2i_X509, &shared_ssl_func__RAND_load_file, &shared_ssl_func__ERR_get_error, &shared_ssl_func__ERR_error_string, NULL }; int i = 0; while (func_name[i] != NULL) { *((int**)(func_ptr[i])) = (int*)dlsym(shared_ssl_lib, func_name[i]); if (*((int**)(func_ptr[i])) == NULL) { fprintf(stderr, "%s: unable to initialize function %s\n", "sgepasswd", func_name[i]); exit(1); } else { DPRINTF(("function "SFQ" successfully initialized\n", func_name[i])); } i++; } ret = 0; } else { fprintf(stderr, "%s\n", MSG_PWD_CANTOPENSSL); ret = 1; } } else { ret = 1; } #else shared_ssl_func__X509_free = X509_free; shared_ssl_func__EVP_PKEY_free = EVP_PKEY_free; shared_ssl_func__ERR_print_errors_fp = ERR_print_errors_fp; shared_ssl_func__EVP_PKEY_size = EVP_PKEY_size; shared_ssl_func__EVP_rc4 = EVP_rc4; shared_ssl_func__EVP_OpenInit = (int (*)(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char *ek, int ekl, unsigned char *iv, EVP_PKEY *priv))EVP_OpenInit; shared_ssl_func__EVP_DecryptUpdate = EVP_DecryptUpdate; shared_ssl_func__EVP_EncryptUpdate = EVP_EncryptUpdate; shared_ssl_func__EVP_SealFinal = EVP_SealFinal; shared_ssl_func__EVP_SealInit = EVP_SealInit; shared_ssl_func__EVP_OpenFinal = EVP_OpenFinal; shared_ssl_func__EVP_read_pw_string = EVP_read_pw_string; shared_ssl_func__ERR_load_crypto_strings = ERR_load_crypto_strings; shared_ssl_func__X509_get_pubkey = X509_get_pubkey; shared_ssl_func__PEM_ASN1_read = (char* (*)(char *(*d2i)(),const char *name,FILE *fp,char **x, pem_password_cb *cb, void *u)) PEM_ASN1_read; shared_ssl_func__d2i_AutoPrivateKey = (EVP_PKEY* (*)(EVP_PKEY **a, unsigned char **pp, long length))d2i_AutoPrivateKey; shared_ssl_func__d2i_X509 = (X509* (*)(X509 **a, unsigned char **in, long len)) d2i_X509; shared_ssl_func__RAND_load_file = RAND_load_file; shared_ssl_func__ERR_get_error = ERR_get_error; shared_ssl_func__ERR_error_string = ERR_error_string; ret = 0; #endif DEXIT; return ret; } int sge_done_shared_ssl_lib(void) { int ret; DENTER(TOP_LAYER, "sge_done_shared_ssl_lib"); #ifdef LOAD_OPENSSL if (shared_ssl_lib != NULL) { shared_ssl_func__X509_free = NULL; shared_ssl_func__EVP_PKEY_free = NULL; shared_ssl_func__ERR_print_errors_fp = NULL; shared_ssl_func__EVP_PKEY_size = NULL; shared_ssl_func__EVP_rc4 = NULL; shared_ssl_func__EVP_OpenInit = NULL; shared_ssl_func__EVP_DecryptUpdate = NULL; shared_ssl_func__EVP_EncryptUpdate = NULL; shared_ssl_func__EVP_SealFinal = NULL; shared_ssl_func__EVP_SealInit = NULL; shared_ssl_func__EVP_OpenFinal = NULL; shared_ssl_func__EVP_read_pw_string = NULL; shared_ssl_func__ERR_load_crypto_strings = NULL; shared_ssl_func__X509_get_pubkey = NULL; shared_ssl_func__PEM_ASN1_read = NULL; shared_ssl_func__d2i_AutoPrivateKey = NULL; shared_ssl_func__d2i_X509 = NULL; shared_ssl_func__RAND_load_file = NULL; dlclose(shared_ssl_lib); shared_ssl_lib = NULL; ret = 0; } else { ret = 1; } #else ret = 0; #endif DEXIT; return ret; } static const char* sge_get_file_pub_key(void) { static char file[4096] = ""; DENTER(TOP_LAYER, "sge_get_file_pub_key"); if (file[0] == '\0') { const char *cert = getenv("SGE_CERTFILE"); if (cert != NULL) { snprintf(file, 4096, cert); } else { const char *sge_root = sge_get_root_dir(0, NULL, 0, 1); const char *sge_cell = sge_get_default_cell(); snprintf(file, 4096, "%s/%s/%s", sge_root, sge_cell, "common/sgeCA/certs/cert.pem"); } } DEXIT; return file; } static const char* sge_get_file_priv_key(void) { static bool initialized = false; static dstring priv_key = DSTRING_INIT; DENTER(TOP_LAYER, "sge_get_file_priv_key"); if (initialized == false) { const char *key = getenv("SGE_KEYFILE"); if (key != NULL) { sge_dstring_append(&priv_key, key); } else { const char *ca_local_dir = "/var/sgeCA"; const char *sge_cell = sge_get_default_cell(); const char *user_key = "private/key.pem"; const char *sge_qmaster_port = getenv("SGE_QMASTER_PORT"); if (sge_qmaster_port != NULL) { sge_dstring_sprintf(&priv_key, "%s/port%s/%s/%s", ca_local_dir, sge_qmaster_port, sge_cell, user_key); } else { sge_dstring_sprintf(&priv_key, "%s/sge_qmaster/%s/%s", ca_local_dir, sge_cell, user_key); } } initialized = true; } DEXIT; return sge_dstring_get_string(&priv_key); } static EVP_PKEY * read_public_key(const char *certfile) { FILE *fp = NULL; X509 *x509; EVP_PKEY *pkey = NULL; DENTER(TOP_LAYER, "read_public_key"); fp = fopen(certfile, "r"); if (!fp) { DEXIT; return NULL; } x509 = shared_ssl_func__PEM_read_X509(fp, NULL, 0, NULL); if (x509 == NULL) { shared_ssl_func__ERR_print_errors_fp(stderr); DEXIT; return NULL; } FCLOSE (fp); pkey = shared_ssl_func__X509_extract_key(x509); shared_ssl_func__X509_free(x509); if (pkey == NULL) { shared_ssl_func__ERR_print_errors_fp(stderr); } FCLOSE_ERROR: DEXIT; return pkey; } static EVP_PKEY * read_private_key(const char *keyfile, char *ssl_err, size_t buff_size) { EVP_PKEY *ret = NULL; FILE *fp = NULL; unsigned long error_code; union { EVP_PKEY *pkey; void *pointer; } pku; DENTER(TOP_LAYER, "read_private_key"); if(keyfile == NULL) { snprintf(ssl_err, buff_size, MSG_PWD_FILE_PATH_NULL_S, SGE_PASSWD_PROG_NAME); DEXIT; return NULL; } fp = fopen(keyfile, "r"); if (!fp) { snprintf(ssl_err, buff_size, MSG_PWD_LOAD_PRIV_SSS, SGE_PASSWD_PROG_NAME, keyfile, MSG_PWD_NO_SSL_ERR); DEXIT; return NULL; } pku.pointer = NULL; #if 1 /* * pointer to pkey must passed into function and will not * be returned by function! */ pku.pkey = shared_ssl_func__PEM_read_PrivateKey(fp, (void*) &pku.pointer, NULL, NULL); #else pku.pkey = PEM_read_PrivateKey(fp, NULL, 0, NULL); #endif FCLOSE(fp); if (pku.pkey == NULL) { error_code = shared_ssl_func__ERR_get_error(); shared_ssl_func__ERR_error_string(error_code, ssl_err); #ifdef DEFINE_SGE_PASSWD_MAIN shared_ssl_func__ERR_print_errors_fp(stderr); #endif } ret = pku.pkey; FCLOSE_ERROR: DEXIT; return ret; } static void buffer_append(char **buffer, size_t *buffer_size, size_t *fill_size, char *buffer_append, size_t size_append) { size_t initial_size = (size_append > 512) ? size_append : 512; DENTER(TOP_LAYER, "buffer_append"); if (*buffer == NULL || *buffer_size == 0) { *buffer_size = initial_size; *buffer = malloc(initial_size); memset(*buffer, 0, *buffer_size); } else if (*fill_size + size_append > *buffer_size) { *buffer_size += size_append; *buffer = sge_realloc(*buffer, *buffer_size, 1); } memcpy(*buffer + *fill_size, buffer_append, size_append); *fill_size += size_append; memset(*buffer + *fill_size, 0, *buffer_size - *fill_size); DEXIT; } #if 0 char * buffer_read_from_stdin(char **buffer, size_t *size) { bool repeat = true; char *buffer_ptr = NULL; size_t buffer_ptr_length = 0; DENTER(TOP_LAYER, "buffer_read_from_stdin"); while (repeat) { char buffer[512]; size_t buffer_length; buffer_length = read(0, buffer, sizeof(buffer)); if (buffer_length <= 0) { if (buffer_length < 0) { fprintf(stderr, "sge_passwd: can't read from stdin\n"); exit(1); } repeat = false; } else { if (buffer_ptr == NULL) { buffer_ptr = malloc(buffer_length + 1); } else { buffer_ptr = sge_realloc(buffer_ptr, strlen(buffer_ptr) + buffer_length, 0); } if (buffer_ptr != NULL) { memcpy(buffer_ptr + buffer_ptr_length, buffer, buffer_length); buffer_ptr_length += buffer_length; } else { fprintf(stderr, MSG_PWD_MALLOC_SS, SGE_PASSWD_PROG_NAME, MSG_PWD_NO_SSL_ERR); exit(1); } } } *buffer = buffer_ptr; *size = (buffer_ptr != NULL) ? strlen(buffer_ptr) : 0; DEXIT; return buffer_ptr; } void buffer_write_to_stdout(const char *buffer, size_t length) { DENTER(TOP_LAYER, "buffer_write_to_stdout"); if (buffer != NULL && length > 0) { write(1, buffer, length); } DEXIT; } #endif int sge_ssl_get_rand_file_path(char *rand_file) { const char *key = getenv("SGE_RANDFILE"); DENTER(TOP_LAYER, "sge_ssl_get_rand_file_path"); if (key != NULL) { sge_strlcpy(rand_file, key, SGE_PATH_MAX); } else { const char *ca_local_dir = "/var/sgeCA"; const char *sge_cell = sge_get_default_cell(); const char *user_key = "private/rand.seed"; const char *sge_qmaster_port = getenv("SGE_QMASTER_PORT"); if (sge_qmaster_port != NULL) { snprintf(rand_file, SGE_PATH_MAX, "%s/port%s/%s/%s", ca_local_dir, sge_qmaster_port, sge_cell, user_key); } else { snprintf(rand_file, SGE_PATH_MAX, "%s/sge_qmaster/%s/%s", ca_local_dir, sge_cell, user_key); } } DEXIT; return 0; } int sge_ssl_rand_load_file(char *rand_file, int max_byte) { int ret; ret = shared_ssl_func__RAND_load_file(rand_file, max_byte); return ret; } void buffer_encrypt(const char *buffer_in, size_t buffer_in_length, char **buffer_out, size_t *buffer_out_size, size_t *buffer_out_length) { unsigned int ebuflen; EVP_CIPHER_CTX ectx; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char *ekey[1]; int ekeylen=0, net_ekeylen=0; EVP_PKEY *pubKey[1]; char ebuf[512]; int ret = 0; char rand_file[SGE_PATH_MAX]; char err_str[MAX_STRING_SIZE]; DENTER(TOP_LAYER, "buffer_encrypt"); pubKey[0] = read_public_key(sge_get_file_pub_key()); if(!pubKey[0]) { fprintf(stderr, MSG_PWD_LOAD_PUB_SS, "sgepasswd", sge_get_file_pub_key()); fprintf(stderr, "\n"); DEXIT; exit(1); } ekey[0] = malloc(shared_ssl_func__EVP_PKEY_size(pubKey[0])); if (!ekey[0]) { shared_ssl_func__EVP_PKEY_free(pubKey[0]); fprintf(stderr, MSG_PWD_MALLOC_SS, SGE_PASSWD_PROG_NAME, MSG_PWD_NO_SSL_ERR); fprintf(stderr, "\n"); DEXIT; exit(1); } /* * Read rand.seed file */ sge_ssl_get_rand_file_path(rand_file); ret = sge_ssl_rand_load_file(rand_file, 1024); if(ret <= 0) { snprintf(err_str, MAX_STRING_SIZE, MSG_PWD_CANTLOADRANDFILE_SSS, "sgepasswd", rand_file, MSG_PWD_NO_SSL_ERR); #ifdef DEFINE_SGE_PASSWD_MAIN fprintf(stderr, "%s\n", err_str); #endif DEXIT; return; } memset(iv, '\0', sizeof(iv)); #if 0 ret = shared_ssl_func__EVP_SealInit(&ectx, EVP_des_ede3_cbc(), ekey, &ekeylen, iv, pubKey, 1); #else ret = shared_ssl_func__EVP_SealInit(&ectx, shared_ssl_func__EVP_rc4(), ekey, &ekeylen, iv, pubKey, 1); #endif if(ret == 0) { printf("---> EVP_SealInit\n"); shared_ssl_func__ERR_print_errors_fp(stdout); } if(ekeylen == 0 || ekeylen > 10000) { DPRINTF(("Setting ekeylen to 128, " "because EVP_SealInit returned invalid value!\n")); ekeylen = 128; } net_ekeylen = htonl(ekeylen); buffer_append(buffer_out, buffer_out_size, buffer_out_length, (char*)&net_ekeylen, sizeof(net_ekeylen)); buffer_append(buffer_out, buffer_out_size, buffer_out_length, (char*)ekey[0], ekeylen); buffer_append(buffer_out, buffer_out_size, buffer_out_length, (char*)iv, sizeof(iv)); shared_ssl_func__EVP_SealUpdate(&ectx, (unsigned char*)ebuf, (int*)&ebuflen, (const unsigned char *) buffer_in, buffer_in_length); buffer_append(buffer_out, buffer_out_size, buffer_out_length, ebuf, ebuflen); shared_ssl_func__EVP_SealFinal(&ectx, (unsigned char *)ebuf, (int*)&ebuflen); buffer_append(buffer_out, buffer_out_size, buffer_out_length, ebuf, ebuflen); shared_ssl_func__EVP_PKEY_free(pubKey[0]); free(ekey[0]); DEXIT; } int buffer_decrypt(const char *buffer_in, size_t buffer_in_length, char **buffer_out, size_t *buffer_out_size, size_t *buffer_out_length, char *err_str) { char buf[520]; char ebuf[512]; unsigned int buflen; EVP_CIPHER_CTX ectx; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char *encryptKey; unsigned int ekeylen; EVP_PKEY *privateKey; char *curr_ptr = (char*)buffer_in; const char *file_priv_key=NULL; char rand_file[SGE_PATH_MAX]; int ret = 0; char ssl_err[MAX_STRING_SIZE]; unsigned long error_code; char err_msg[MAX_STRING_SIZE]; DENTER(TOP_LAYER, "buffer_decrypt"); memset(iv, '\0', sizeof(iv)); file_priv_key = sge_get_file_priv_key(); privateKey = read_private_key(file_priv_key, ssl_err, MAX_STRING_SIZE); if (!privateKey) { snprintf(err_str, MAX_STRING_SIZE, MSG_PWD_LOAD_PRIV_SSS, SGE_PASSWD_PROG_NAME, file_priv_key, err_msg); #ifdef DEFINE_SGE_PASSWD_MAIN fprintf(stderr, err_str); #endif DEXIT; return 1; } memcpy(&ekeylen, curr_ptr, sizeof(ekeylen)); curr_ptr += sizeof(ekeylen); buffer_in_length -= sizeof(ekeylen); ekeylen = ntohl(ekeylen); if (ekeylen != shared_ssl_func__EVP_PKEY_size(privateKey)) { shared_ssl_func__EVP_PKEY_free(privateKey); error_code = shared_ssl_func__ERR_get_error(); shared_ssl_func__ERR_error_string(error_code, err_msg); snprintf(err_str, MAX_STRING_SIZE, MSG_PWD_DECR_SS, SGE_PASSWD_PROG_NAME, err_msg); #ifdef DEFINE_SGE_PASSWD_MAIN fprintf(stderr, "%s\n", err_str); #endif DEXIT; return 1; } encryptKey = malloc(sizeof(char) * ekeylen); if (!encryptKey) { shared_ssl_func__EVP_PKEY_free(privateKey); error_code = shared_ssl_func__ERR_get_error(); shared_ssl_func__ERR_error_string(error_code, err_msg); snprintf(err_str, MAX_STRING_SIZE, MSG_PWD_MALLOC_SS, SGE_PASSWD_PROG_NAME, err_msg); #ifdef DEFINE_SGE_PASSWD_MAIN fprintf(stderr, err_str); #endif DEXIT; return 1; } /* * Read rand.seed file */ sge_ssl_get_rand_file_path(rand_file); ret = sge_ssl_rand_load_file(rand_file, 1024); if(ret <= 0) { error_code = shared_ssl_func__ERR_get_error(); shared_ssl_func__ERR_error_string(error_code, err_msg); snprintf(err_str, MAX_STRING_SIZE, MSG_PWD_CANTLOADRANDFILE_SSS, SGE_PASSWD_PROG_NAME, rand_file, err_msg); #ifdef DEFINE_SGE_PASSWD_MAIN fprintf(stderr, "%s\n", err_str); #endif DEXIT; return 1; } memcpy(encryptKey, curr_ptr, ekeylen); curr_ptr += ekeylen; buffer_in_length -= ekeylen; memcpy(&iv, curr_ptr, sizeof(iv)); curr_ptr += sizeof(iv); buffer_in_length -= sizeof(iv); #if 0 ret = shared_ssl_func__EVP_OpenInit(&ectx, EVP_des_ede3_cbc(), encryptKey, ekeylen, iv, privateKey); #else ret = shared_ssl_func__EVP_OpenInit(&ectx, shared_ssl_func__EVP_rc4(), encryptKey, ekeylen, iv, privateKey); #endif if(ret == 0) { printf("----> EVP_OpenInit\n"); shared_ssl_func__ERR_print_errors_fp(stdout); } while (buffer_in_length > 0) { int readlen = 0; if (buffer_in_length < sizeof(ebuf)) { memcpy(&ebuf, curr_ptr, buffer_in_length); readlen = buffer_in_length; buffer_in_length = 0; } else { memcpy(&ebuf, curr_ptr, sizeof(ebuf)); curr_ptr += sizeof(ebuf); buffer_in_length -= sizeof(ebuf); readlen = sizeof(ebuf); } ret = shared_ssl_func__EVP_OpenUpdate(&ectx, (unsigned char *)buf, (int*)&buflen, (const unsigned char *)ebuf, readlen); if (ret == 0) { error_code = shared_ssl_func__ERR_get_error(); shared_ssl_func__ERR_error_string(error_code, err_msg); snprintf(err_str, MAX_STRING_SIZE, MSG_PWD_SSL_ERR_MSG_SS, SGE_PASSWD_PROG_NAME, err_msg); #ifdef DEFINE_SGE_PASSWD_MAIN fprintf(stderr, "%s\n", err_str); #endif DEXIT; return 1; } buffer_append(buffer_out, buffer_out_size, buffer_out_length, buf, buflen); } ret = shared_ssl_func__EVP_OpenFinal(&ectx, (unsigned char *)buf, (int*)&buflen); if (ret == 0) { error_code = shared_ssl_func__ERR_get_error(); shared_ssl_func__ERR_error_string(error_code, err_msg); snprintf(err_str, MAX_STRING_SIZE, MSG_PWD_SSL_ERR_MSG_SS, SGE_PASSWD_PROG_NAME, err_msg); #ifdef DEFINE_SGE_PASSWD_MAIN fprintf(stderr, "%s\n", err_str); #endif DEXIT; return 1; } buffer_append(buffer_out, buffer_out_size, buffer_out_length, buf, buflen); shared_ssl_func__EVP_PKEY_free(privateKey); free(encryptKey); error_code = shared_ssl_func__ERR_get_error(); if(error_code > 0) { shared_ssl_func__ERR_error_string(error_code, err_msg); snprintf(err_str, MAX_STRING_SIZE, MSG_PWD_SSL_ERR_MSG_SS, SGE_PASSWD_PROG_NAME, err_msg); #ifdef DEFINE_SGE_PASSWD_MAIN fprintf(stderr, "%s\n", err_str); #endif DEXIT; return 1; } DEXIT; return 0; } const char* sge_get_file_dotpasswd(void) { static char file[4096] = ""; DENTER(TOP_LAYER, "sge_get_file_dotpasswd"); if (file[0] == '\0') { const char *sge_root = sge_get_root_dir(0, NULL, 0, 1); const char *sge_cell = sge_get_default_cell(); snprintf(file, 4096, "%s/%s/common/.sgepasswd", sge_root, sge_cell); } DEXIT; return file; } unsigned char * buffer_encode_hex(unsigned char *input, size_t len, unsigned char **output) { size_t s; int ret; DENTER(TOP_LAYER, "buffer_encode_hex"); s = len * 2 + 1; DPRINTF(("len=%d, mallocing %d Bytes\n", len, s)); *output = malloc(s); DPRINTF(("buffer output=%#x\n", *output)); if(*output != NULL) { memset(*output, 0, s); for (s = 0; s < len; s++) { char buffer[32] = ""; int byte = input[s]; ret = snprintf(buffer, 3, "%02x", byte); if(ret != 2) { DPRINTF(("encode error: snprintf returned %d\n", ret)); free(*output); *output=NULL; return NULL; } strcat((char*) *output, buffer); } } DEXIT; return *output; } unsigned char * buffer_decode_hex(unsigned char *input, size_t *len, unsigned char **output) { size_t s; DENTER(TOP_LAYER, "buffer_decode_hex"); s = *len / 2 + 1; *output = malloc(s); memset(*output, 0, s); for (s = 0; s < *len; s+=2) { char buffer[32] = ""; int byte = 0; buffer[0] = input[s]; buffer[1] = input[s+1]; sscanf(buffer, "%02x", &byte); (*output)[s/2] = byte; } *len = *len / 2; DEXIT; return *output; } #ifdef DEFINE_SGE_PASSWD_MAIN static void password_write_file(char *users[], char *encryped_pwds[], const char *backup_file, const char *filename) { FILE *fp = NULL; size_t i = 0; DENTER(TOP_LAYER, "password_write_file"); FOPEN(fp, backup_file, "w"); while (users[i] != NULL) { if (users[i][0] != '\0') { FPRINTF((fp, "%s %s\n", users[i], encryped_pwds[i])); } i++; } FCLOSE(fp); rename(backup_file, filename); goto FUNC_EXIT; FOPEN_ERROR: fprintf(stderr, MSG_PWD_OPEN_SGEPASSWD_SSI, SGE_PASSWD_PROG_NAME, strerror(errno), errno); goto FUNC_EXIT; FPRINTF_ERROR: fprintf(stderr, MSG_PWD_WRITE_SGEPASSWD_SSI, SGE_PASSWD_PROG_NAME, strerror(errno), errno); FCLOSE(fp); goto FUNC_EXIT; FCLOSE_ERROR: fprintf(stderr, MSG_PWD_CLOSE_SGEPASSWD_SSI, SGE_PASSWD_PROG_NAME, strerror(errno), errno); goto FUNC_EXIT; FUNC_EXIT: fprintf(stderr, "\n"); DEXIT; } static void password_add_or_replace_entry(char **users[], char **encryped_pwds[], const char *user, const char *encryped_pwd) { size_t i = 0; bool done = false; DENTER(TOP_LAYER, "password_add_or_replace_entry"); while ((*users)[i] != NULL) { if (!strcmp((*users)[i], user)) { free((*encryped_pwds)[i]); (*encryped_pwds)[i] = strdup(encryped_pwd); done = true; } i++; } if (!done) { (*users)[i] = strdup(user); (*encryped_pwds)[i] = strdup(encryped_pwd); } DEXIT; } static void sge_passwd_delete(const char *username, const char *domain) { char user[256] = ""; char **users = NULL; char **encryped_pwd = NULL; int i; /* * Read password table */ if (password_read_file(&users, &encryped_pwd, sge_get_file_passwd()) == 2) { fprintf(stderr, MSG_PWD_FILE_CORRUPTED_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(1); } if (domain != NULL && domain[0] != '\0') { strcpy(user, domain); strcat(user, "+"); strcat(user, username); } else { strcpy(user, username); } /* * replace username by zero byte */ i = password_find_entry(users, encryped_pwd, user); if (i != -1) { users[i][0] = '\0'; } /* * write new password table */ password_write_file(users, encryped_pwd, sge_get_file_dotpasswd(), sge_get_file_passwd()); } #if 0 static void sge_passwd_show(const char *username) { char user[128] = ""; char **users = NULL; char **encryped_pwd = NULL; DENTER(TOP_LAYER, "sge_passwd_add_change"); /* * Get user name */ if (username != NULL) { strcpy(user, username); } else { uid_t uid = getuid(); if (sge_uid2user(uid, user, sizeof(user), MAX_NIS_RETRIES)) { fprintf(stderr, MSG_PWD_NO_USERNAME_SU, SGE_PASSWD_PROG_NAME, uid); exit(7); } } /* * Read password table */ if (password_read_file(&users, &encryped_pwd, sge_get_file_passwd()) == 2) { fprintf(stderr, MSG_PWD_FILE_CORRUPTED_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(1); } /* * Check if there is an old entry in the password file * if it exists then check if the current users knows that pwd */ { int i = password_find_entry(users, encryped_pwd, user); if (i != -1) { unsigned char *buffer_deco = NULL; size_t buffer_deco_length = 0; char *buffer_decr = NULL; size_t buffer_decr_size = 0; size_t buffer_decr_length = 0; int err64 = 0; buffer_deco_length = strlen(encryped_pwd[i]); buffer_decode_base64(encryped_pwd[i], &buffer_deco_length, 0, &err64, &buffer_deco); if(buffer_decrypt(buffer_deco, buffer_deco_length, &buffer_decr, &buffer_decr_size, &buffer_decr_length)!=0) { exit(1); } fprintf(stdout, "%s\n", buffer_decr); if (buffer_deco != NULL) { free(buffer_deco); } if (buffer_decr != NULL) { free(buffer_decr); } } } DEXIT; } #endif static void sge_passwd_add_change(const char *username, const char *domain, uid_t uid) { char user[128+128] = ""; /* actually (128-1) + (1) + (128-1) + (1) */ char **users = NULL; char **encryped_pwd = NULL; char err_str[MAX_STRING_SIZE]; DENTER(TOP_LAYER, "sge_passwd_add_change"); if (domain != NULL && domain[0] != '\0') { strcpy(user, domain); strcat(user, "+"); strcat(user, username); } else { strcpy(user, username); } DPRINTF(("username: %s\n", user)); fprintf(stdout, MSG_PWD_CHANGE_FOR_S, user); fprintf(stdout, "\n"); /* * Read password table */ if (password_read_file(&users, &encryped_pwd, sge_get_file_passwd()) == 2){ fprintf(stderr, MSG_PWD_FILE_CORRUPTED_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(1); } DPRINTF(("read password table\n")); /* * Check if there is an old entry in the password file and if user is * not root if it exists then check if the current users knows that pwd */ if (uid != 0) { int i = password_find_entry(users, encryped_pwd, user); if (i != -1) { char old_passwd[128] = ""; unsigned char *buffer_deco = NULL; size_t buffer_deco_length = 0; char *buffer_decr = NULL; size_t buffer_decr_size = 0; size_t buffer_decr_length = 0; #if 0 int err64 = 0; #endif if (shared_ssl_func__EVP_read_pw_string(old_passwd, 128, "Old password: ", 0) != 0) { fprintf(stderr, MSG_PWD_CHANGE_ABORT_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(2); } buffer_deco_length = strlen(encryped_pwd[i]); #if 0 buffer_decode_base64(encryped_pwd[i], &buffer_deco_length, 0, &err64, &buffer_deco); #else buffer_decode_hex((unsigned char*)encryped_pwd[i], &buffer_deco_length, &buffer_deco); #endif if(buffer_decrypt((const char*)buffer_deco, buffer_deco_length, &buffer_decr, &buffer_decr_size, &buffer_decr_length, err_str)!=0) { exit(1); } if (strncmp(buffer_decr, old_passwd, 128)) { fprintf(stderr, MSG_PWD_AUTH_FAILURE_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(7); } DPRINTF(("verified old password\n")); if (buffer_deco != NULL) { free(buffer_deco); } if (buffer_decr != NULL) { free(buffer_decr); } } } /* * Ask for new password twice and add/replace that password */ { char new_passwd[128] = ""; char new_passwd2[128] = ""; char *buffer_encr = NULL; size_t buffer_encr_size = 0; size_t buffer_encr_length = 0; unsigned char *buffer_enco = NULL; if (shared_ssl_func__EVP_read_pw_string(new_passwd, 128, "New password: ", 0) != 0) { fprintf(stderr, MSG_PWD_CHANGE_ABORT_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(2); } if (shared_ssl_func__EVP_read_pw_string(new_passwd2, 128, "Re-enter new password: ", 0) != 0) { fprintf(stderr, MSG_PWD_CHANGE_ABORT_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(2); } if (strncmp(new_passwd, new_passwd2, 128)) { fprintf(stderr, MSG_PWD_NO_MATCH_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(7); } DPRINTF(("passwords are equivalent\n")); if (strlen(new_passwd) == 0) { fprintf(stderr, MSG_PWD_INVALID_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(7); } DPRINTF(("new password is valid\n")); buffer_encrypt(new_passwd, strlen(new_passwd), &buffer_encr, &buffer_encr_size, &buffer_encr_length); #if 0 buffer_encode_base64(buffer_encr, buffer_encr_length, 0, &buffer_enco); #else buffer_encode_hex((unsigned char*)buffer_encr, (size_t)buffer_encr_length, &buffer_enco); #endif password_add_or_replace_entry(&users, &encryped_pwd, user, (const char *)buffer_enco); if (buffer_encr != NULL) { free(buffer_encr); } if (buffer_enco != NULL) { free(buffer_enco); } } /* * write new password table */ password_write_file(users, encryped_pwd, sge_get_file_dotpasswd(), sge_get_file_passwd()); DPRINTF(("password table has been written\n")); fprintf(stdout, MSG_PWD_CHANGED); fprintf(stdout, "\n"); DEXIT; } static void passwd_become_admin_user(const char *admin_user) { char str[1024]; DENTER(TOP_LAYER, "passwd_become_admin_user"); if (sge_set_admin_username(admin_user, str) == -1) { fprintf(stderr, SFN": "SFN"\n", SGE_PASSWD_PROG_NAME, str); fprintf(stderr, "\n"); exit(1); } if (sge_switch2admin_user()) { fprintf(stderr, MSG_PWD_SWITCH_ADMIN_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(1); } DEXIT; return; } static void sge_passwd_show_usage(void) { DENTER(TOP_LAYER, "sge_passwd_show_usage"); printf("usage: sgepasswd [[-D domain>] -d user] | [-D domain] [user]\n"); printf(" [-help] display this message\n"); printf(" [-D domain ] add the given domain name to the user name\n"); printf(" [-d user ] delete the password for the named account\n"); printf(" domain windows domain name\n"); printf(" user windows users without domain name specification\n"); DEXIT; } int main(int argc, char *argv[]) { char domain[128] = ""; char username[128] = ""; bool do_delete = false; uid_t starter_uid=(uid_t)-1; char buffer[1024]; dstring bw; const char *bootstrap_file = NULL; const char *admin_user = NULL; DENTER_MAIN(TOP_LAYER, "sgepasswd"); prof_mt_init(); uidgid_mt_init(); path_mt_init(); bootstrap_mt_init(); /* * Do initalisation and switch to admin_user */ /* * Check if euid is right, then switch to root */ DPRINTF(("uid=%ld; gid=%ld; euid=%ld; egid=%ld\n", (long)getuid(), (long)getgid(), (long)geteuid(), (long)getegid())); if(geteuid()!=SGE_SUPERUSER_UID) { fprintf(stderr, SFN": Not Superuser, check file permissions!\n", SGE_PASSWD_PROG_NAME); exit(1); } if(sge_init_shared_ssl_lib()!=0) { exit(1); } shared_ssl_func__ERR_load_crypto_strings(); sge_dstring_init(&bw, buffer, sizeof(buffer)); sge_getme(SGE_PASSWD); if (sge_setup_paths(SGE_PASSWD, sge_get_default_cell(), &bw) != true) { fprintf(stderr, SFN": "SFN"\n", SGE_PASSWD_PROG_NAME, sge_dstring_get_string(&bw)); exit(1); } bootstrap_file = path_state_get_bootstrap_file(); if (sge_bootstrap(bootstrap_file, &bw) != true) { fprintf(stderr, SFN": "SFN"\n", SGE_PASSWD_PROG_NAME, sge_dstring_get_string(&bw)); exit(1); } admin_user = bootstrap_get_admin_user(); /* * switch to root */ starter_uid = getuid(); setuid(SGE_SUPERUSER_UID); setgid(SGE_SUPERUSER_GID); DPRINTF(("uid=%ld; gid=%ld; euid=%ld; egid=%ld\n", (long)getuid(), (long)getgid(), (long)geteuid(), (long)getegid())); passwd_become_admin_user(admin_user); DPRINTF(("uid=%ld; gid=%ld; euid=%ld; egid=%ld\n", (long)getuid(), (long)getgid(), (long)geteuid(), (long)getegid())); while (argc > 1) { if (!strcmp(argv[1],"-help")) { argc--; argv++; sge_passwd_show_usage(); DEXIT; exit(1); } if (!strcmp(argv[1],"-D")) { argc--; argv++; if (argc != 1 && strncpy(domain, argv[1], sizeof(domain)) && domain[0] != '\0') { domain[sizeof(domain)-1] = '\0'; argc--; argv++; continue; } else { sge_passwd_show_usage(); DEXIT; exit(1); } } if (!strcmp(argv[1],"-d")) { uid_t uid = getuid(); if (uid != 0) { fprintf(stderr, MSG_PWD_ONLY_ROOT_S, SGE_PASSWD_PROG_NAME); fprintf(stderr, "\n"); exit(1); } argc--; argv++; if (argc != 1 && strncpy(username, argv[1], sizeof(username)) && username[0] != '\0') { username[sizeof(username)-1] = '\0'; argc--; argv++; do_delete = true; continue; } else { sge_passwd_show_usage(); DEXIT; exit(1); } } if (argv[1][0] != '-' && strncpy(username, argv[1], sizeof(username)) && username[0] != '\0') { uid_t uid = getuid(); username[sizeof(username)-1] = '\0'; if (uid != 0) { fprintf(stderr, MSG_PWD_ONLY_USER_SS, SGE_PASSWD_PROG_NAME, username); fprintf(stderr, "\n"); exit(1); } argc--; argv++; continue; } } if (username == NULL || username[0] == '\0') { if (sge_uid2user(starter_uid, username, sizeof(username), MAX_NIS_RETRIES)) { fprintf(stderr, MSG_PWD_NO_USERNAME_SU, SGE_PASSWD_PROG_NAME, sge_u32c(starter_uid)); fprintf(stderr, "\n"); exit(7); } } if (do_delete) { sge_passwd_delete(username, domain); } else { sge_passwd_add_change(username, domain, starter_uid); } sge_done_shared_ssl_lib(); DEXIT; return 0; } #endif /* defined( DEFINE_SGE_PASSWD_MAIN ) */ #else /* defined( SECURE ) */ #if defined( DEFINE_SGE_PASSWD_MAIN ) int main(void) { printf("sgepasswd built with option -no-secure and therefore not functional.\n"); return 1; } #endif /* defined( DEFINE_SGE_PASSWD_MAIN ) */ #endif /* defined( SECURE ) */