00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00038 #define USE_GCRYPT_MALLOC_SECURE
00039
00040 #include "libnuclient.h"
00041 #include "nuclient.h"
00042 #include "nufw_source.h"
00043 #include <sasl/sasl.h>
00044 #include <sasl/saslutil.h>
00045 #include <stdarg.h>
00046 #include <langinfo.h>
00047 #include <proto.h>
00048 #include "security.h"
00049 #include "sys_config.h"
00050 #include "internal.h"
00051 #include "tcptable.h"
00052 #include <sys/utsname.h>
00053
00054 #include <nussl.h>
00055 #include <nubase.h>
00056
00057
00058 void nu_exit_clean(nuauth_session_t * session)
00059 {
00060 if (session->ct) {
00061 tcptable_free(session->ct);
00062 }
00063
00064 if(session->nussl)
00065 {
00066 nussl_session_destroy(session->nussl);
00067 session->nussl = NULL;
00068 }
00069
00070 secure_str_free(session->username);
00071 secure_str_free(session->password);
00072
00073 free(session);
00074 }
00075
00101 void nu_client_delete(nuauth_session_t * session)
00102 {
00103 ask_session_end(session);
00104
00105 nu_exit_clean(session);
00106 }
00107
00118 int nu_client_global_init(nuclient_error_t * err)
00119 {
00120 int ret;
00121
00122 if (nussl_init() != NUSSL_OK)
00123 {
00124 SET_ERROR(err, INTERNAL_ERROR, NUSSL_INIT_ERR);
00125 return 0;
00126 }
00127
00128
00129 ret = sasl_client_init(NULL);
00130 if (ret != SASL_OK) {
00131 SET_ERROR(err, SASL_ERROR, ret);
00132 return 0;
00133 }
00134
00135 nu_locale_charset = nl_langinfo(CODESET);
00136 if (nu_locale_charset == NULL) {
00137 fprintf(stderr, "Can't get locale charset!\n");
00138 exit(EXIT_FAILURE);
00139 }
00140
00141 load_sys_config();
00142
00143 return 1;
00144 }
00145
00152 void nu_client_global_deinit()
00153 {
00154 sasl_done();
00155 }
00156
00162 void nu_client_set_username(nuauth_session_t *session,
00163 const char *username)
00164 {
00165 char *utf8username = nu_client_to_utf8(username, nu_locale_charset);
00166 session->username = secure_str_copy(utf8username);
00167 free(utf8username);
00168 }
00169
00175 void nu_client_set_password(nuauth_session_t *session,
00176 const char *password)
00177 {
00178 char *utf8pass = nu_client_to_utf8(password, nu_locale_charset);
00179 session->password = secure_str_copy(utf8pass);
00180 free(utf8pass);
00181 }
00182
00183 void nu_client_set_debug(nuauth_session_t * session, unsigned char enabled);
00184
00192 char *nu_get_home_dir()
00193 {
00194 uid_t uid;
00195 struct passwd *pwd;
00196 char *dir = NULL;
00197
00198 uid = getuid();
00199 if (!(pwd = getpwuid(uid))) {
00200 printf("Unable to get password file record\n");
00201 endpwent();
00202 return NULL;
00203 }
00204 dir = strdup(pwd->pw_dir);
00205 endpwent();
00206 return dir;
00207 }
00208
00216 char *nu_get_user_name()
00217 {
00218 uid_t uid;
00219 struct passwd *pwd;
00220 char *name = NULL;
00221
00222 uid = getuid();
00223 if (!(pwd = getpwuid(uid))) {
00224 printf("Unable to get password file record\n");
00225 endpwent();
00226 return NULL;
00227 }
00228 name = strdup(pwd->pw_name);
00229 endpwent();
00230 return name;
00231 }
00232
00233 int nu_client_set_key(nuauth_session_t* session, char* keyfile, char* certfile, nuclient_error_t* err)
00234 {
00235 if (session->pem_key)
00236 free(session->pem_key);
00237
00238 if (session->pem_cert)
00239 free(session->pem_cert);
00240
00241 if (keyfile)
00242 {
00243 session->pem_key = strdup(keyfile);
00244 printf("Using key: %s\n", keyfile);
00245 }
00246
00247 if (certfile)
00248 {
00249 session->pem_cert = strdup(certfile);
00250 printf("Using certificate: %s\n", certfile);
00251 }
00252
00253 return 1;
00254 }
00255
00256 int nu_client_set_ca(nuauth_session_t* session, char* cafile, nuclient_error_t* err)
00257 {
00258 if (session->pem_ca)
00259 free(session->pem_ca);
00260
00261 if (cafile)
00262 session->pem_ca = strdup(cafile);
00263
00264 printf("Using CA: %s\n", cafile);
00265 return 1;
00266 }
00267
00268 int nu_client_set_pkcs12(nuauth_session_t* session, char* key_file, char* key_password, nuclient_error_t* err)
00269 {
00270 if (session->pkcs12_file)
00271 free(session->pkcs12_file);
00272
00273 if (session->pkcs12_password)
00274 free(session->pkcs12_password);
00275
00276 if (key_file)
00277 {
00278 printf("Using key: %s\n", key_file);
00279 session->pkcs12_file = strdup(key_file);
00280 }
00281
00282 if (key_password)
00283 session->pkcs12_password = strdup(key_password);
00284
00285 return 1;
00286 }
00299 int nu_client_load_key(nuauth_session_t * session,
00300 char *keyfile, char *certfile,
00301 nuclient_error_t * err)
00302 {
00303 char certstring[256];
00304 char keystring[256];
00305 char *home = nu_get_home_dir();
00306 int exit_on_error = 0;
00307 int ret;
00308
00309
00310
00311
00312
00313 if (certfile || keyfile)
00314 exit_on_error = 1;
00315
00316
00317 if (keyfile == NULL && home != NULL) {
00318 ret = secure_snprintf(keystring, sizeof(keystring),
00319 "%s/.nufw/key.pem", home);
00320 if (ret)
00321 keyfile = keystring;
00322 }
00323
00324 if (certfile == NULL && home != NULL) {
00325 ret = secure_snprintf(certstring, sizeof(certstring),
00326 "%s/.nufw/cert.pem", home);
00327 if (ret)
00328 certfile = certstring;
00329 }
00330
00331 if (certfile != NULL || keyfile != NULL) {
00332 ret =
00333 nussl_ssl_set_keypair(session->nussl, certfile, keyfile);
00334
00335 if (ret != NUSSL_OK) {
00336 if (exit_on_error) {
00337 if (home)
00338 free(home);
00339 SET_ERROR(err, NUSSL_ERR, ret);
00340 return 0;
00341 }
00342 else {
00343 printf("Warning: Failed to load default certificate and key.\n");
00344 }
00345 }
00346 }
00347
00348 if (home)
00349 free(home);
00350
00351 return 1;
00352 }
00353
00354
00367 int nu_client_load_pkcs12(nuauth_session_t * session,
00368 char *pkcs12file, char *pkcs12password,
00369 nuclient_error_t * err)
00370 {
00371 int ret = nussl_ssl_set_pkcs12_keypair(session->nussl, pkcs12file, pkcs12password);
00372 if (ret != NUSSL_OK)
00373 {
00374 SET_ERROR(err, NUSSL_ERR, ret);
00375 return 0;
00376 }
00377 return 1;
00378 }
00379
00380
00391 int nu_client_load_ca(nuauth_session_t * session,
00392 char *cafile,
00393 nuclient_error_t * err)
00394 {
00395 char castring[256];
00396 char *home = nu_get_home_dir();
00397 int exit_on_error = 0;
00398 int ret;
00399
00400 if (cafile != NULL)
00401 exit_on_error = 1;
00402
00403 if (cafile == NULL && home != NULL) {
00404 ret = secure_snprintf(castring, sizeof(castring),
00405 "%s/.nufw/cacert.pem", home);
00406 if (ret)
00407 cafile = castring;
00408 }
00409
00410 if (cafile != NULL) {
00411 ret = nussl_ssl_trust_cert_file(session->nussl, cafile);
00412 if (ret != NUSSL_OK) {
00413 if (exit_on_error) {
00414 if (home)
00415 free(home);
00416 SET_ERROR(err, NUSSL_ERR, ret);
00417 return 0;
00418 }
00419 else {
00420 if (!session->suppress_ca_warning) {
00421 fprintf(stderr,"\nWARNING: you have not provided any certificate authority.\n"
00422 "nutcpc will *NOT* verify server certificate trust.\n"
00423 "Use the -A <cafile> option to set up CA.\n\n"
00424 );
00425 }
00426 session->suppress_fqdn_verif = 1;
00427 nussl_set_session_flag(session->nussl, NUSSL_SESSFLAG_IGNORE_ID_MISMATCH, 1);
00428 }
00429 }
00430 } else {
00431 fprintf(stderr, "Could not load any CA !\n");
00432 return 0;
00433 }
00434 return 1;
00435 }
00436
00437 int nu_client_load_crl(nuauth_session_t *session, const char *crlfile,
00438 const char *cafile, nuclient_error_t * err)
00439 {
00440 int ret;
00441 if (crlfile && *crlfile) {
00442 ret = nussl_ssl_set_crl_file(session->nussl, crlfile);
00443 if (ret != NUSSL_OK) {
00444 fprintf(stderr,"TLS error with CRL: %s",
00445 nussl_get_error(session->nussl));
00446 return 0;
00447 }
00448 printf("Using crl: %s\n", crlfile);
00449 }
00450 return 1;
00451 }
00452
00460 char* nu_client_get_cert_infos(nuauth_session_t * session)
00461 {
00462 return nussl_get_cert_infos(session->nussl);
00463 }
00464
00465
00473 char* nu_client_get_server_cert_infos(nuauth_session_t * session)
00474 {
00475 return nussl_get_server_cert_infos(session->nussl);
00476 }
00477
00478
00482 int nu_client_set_nuauth_cert_dn(nuauth_session_t * session,
00483 char *nuauth_cert_dn,
00484 nuclient_error_t *err)
00485 {
00486 if (*nuauth_cert_dn) {
00487 session->nuauth_cert_dn = nuauth_cert_dn;
00488 }
00489 return 1;
00490 }
00491
00495 int nu_client_set_crlfile(nuauth_session_t * session,
00496 char *crlfile,
00497 nuclient_error_t *err)
00498 {
00499 if (session->pem_crl)
00500 free(session->pem_crl);
00501
00502 if (crlfile)
00503 session->pem_crl = strdup(crlfile);
00504
00505 return 1;
00506 }
00507
00511 int nu_client_set_krb5_service(nuauth_session_t * session,
00512 char *service)
00513 {
00514 if (service) {
00515 session->krb5_service = service;
00516 }
00517 return 1;
00518 }
00519
00523 int nu_client_set_ca_suppress_warning(nuauth_session_t * session,
00524 int suppress_ca_warning)
00525 {
00526 session->suppress_ca_warning = suppress_ca_warning;
00527 return 1;
00528 }
00529
00533 int nu_client_set_fqdn_suppress_verif(nuauth_session_t * session,
00534 int suppress_fqdn_verif)
00535 {
00536 session->suppress_fqdn_verif = suppress_fqdn_verif;
00537 return 1;
00538 }
00539
00547 void nu_client_set_source(nuauth_session_t *session, struct sockaddr_storage *addr)
00548 {
00549 session->has_src_addr = 1;
00550 session->src_addr = *addr;
00551 }
00552
00568 nuauth_session_t *_nu_client_new(nuclient_error_t * err)
00569 {
00570 conntable_t *new;
00571 nuauth_session_t *session;
00572
00573
00574 SET_ERROR(err, INTERNAL_ERROR, NO_ERR);
00575
00576
00577 session = (nuauth_session_t *) calloc(1, sizeof(nuauth_session_t));
00578 if (session == NULL) {
00579 SET_ERROR(err, INTERNAL_ERROR, MEMORY_ERR);
00580 return NULL;
00581 }
00582
00583
00584 session->userid = getuid();
00585 session->connected = 0;
00586 session->auth_by_default = 1;
00587 session->packet_seq = 0;
00588 session->ct = NULL;
00589 session->debug_mode = 0;
00590 session->verbose = 1;
00591 session->timestamp_last_sent = time(NULL);
00592 session->min_sleep_delay.tv_sec = MIN_DELAY_SEC;
00593 session->min_sleep_delay.tv_usec = MIN_DELAY_USEC;
00594 session->max_sleep_delay.tv_sec = MAX_DELAY_SEC;
00595 session->max_sleep_delay.tv_usec = MAX_DELAY_USEC;
00596 session->sleep_delay.tv_sec = MIN_DELAY_SEC;
00597 session->sleep_delay.tv_usec = MIN_DELAY_USEC;
00598
00599 if (tcptable_init(&new) == 0) {
00600 SET_ERROR(err, INTERNAL_ERROR, MEMORY_ERR);
00601 nu_exit_clean(session);
00602 return NULL;
00603 }
00604 session->ct = new;
00605
00606 return session;
00607 }
00608
00624 nuauth_session_t *nu_client_new_callback(void *username_callback,
00625 void *passwd_callback,
00626 unsigned char diffie_hellman, nuclient_error_t * err)
00627 {
00628 nuauth_session_t *session = NULL;
00629
00630 if (username_callback == NULL || passwd_callback == NULL) {
00631 SET_ERROR(err, INTERNAL_ERROR, BAD_CREDENTIALS_ERR);
00632 return NULL;
00633 }
00634
00635 session = _nu_client_new(err);
00636
00637 session->username_callback = username_callback;
00638 session->passwd_callback = passwd_callback;
00639
00640 return session;
00641 }
00642
00658 nuauth_session_t *nu_client_new(const char *username,
00659 const char *password,
00660 unsigned char diffie_hellman, nuclient_error_t * err)
00661 {
00662 nuauth_session_t *session = NULL;
00663
00664 if (username == NULL || password == NULL) {
00665 SET_ERROR(err, INTERNAL_ERROR, BAD_CREDENTIALS_ERR);
00666 return NULL;
00667 }
00668
00669 session = _nu_client_new(err);
00670
00671 session->username = secure_str_copy(username);
00672 session->password = secure_str_copy(password);
00673 if (session->username == NULL || session->password == NULL) {
00674 SET_ERROR(err, INTERNAL_ERROR, MEMORY_ERR);
00675 return NULL;
00676 }
00677
00678 return session;
00679 }
00680
00686 void nu_client_reset(nuauth_session_t * session)
00687 {
00688 ask_session_end(session);
00689
00690
00691 session->connected = 0;
00692 session->timestamp_last_sent = time(NULL);
00693 }
00694
00709 int nu_client_connect(nuauth_session_t * session,
00710 const char *hostname, const char *service,
00711 nuclient_error_t * err)
00712 {
00713 int ret;
00714 unsigned int port = atoi(service);
00715
00716 session->nussl = nussl_session_create();
00717
00718 if (session->suppress_fqdn_verif)
00719 nussl_set_session_flag(session->nussl, NUSSL_SESSFLAG_IGNORE_ID_MISMATCH, 1);
00720
00721 nussl_set_hostinfo(session->nussl, hostname, port);
00722 if(session->pkcs12_file)
00723 {
00724 if (!nu_client_load_pkcs12(session, session->pkcs12_file, session->pkcs12_password, err))
00725 return 0;
00726 }
00727 else
00728 {
00729 if (!nu_client_load_key(session, session->pem_key, session->pem_cert, err))
00730 return 0;
00731 }
00732
00733 if (!nu_client_load_ca(session, session->pem_ca, err))
00734 return 0;
00735
00736 if (session->pem_crl) {
00737 if (!nu_client_load_crl(session, session->pem_crl, session->pem_ca, err))
00738 return 0;
00739 }
00740
00741 ret = nussl_open_connection(session->nussl);
00742 if (ret != NUSSL_OK) {
00743 nussl_session_destroy(session->nussl);
00744 session->nussl = NULL;
00745 SET_ERROR(err, NUSSL_ERR, ret);
00746 return 0;
00747 }
00748
00749 if (!init_sasl(session, hostname, err)) {
00750 return 0;
00751 }
00752
00753 if (!send_os(session, err)) {
00754 return 0;
00755 }
00756 session->connected = 1;
00757 return 1;
00758 }
00759
00767 void nu_client_set_debug(nuauth_session_t * session, unsigned char enabled)
00768 {
00769 session->debug_mode = enabled;
00770 }
00771
00772
00780 void nu_client_set_verbose(nuauth_session_t * session, unsigned char enabled)
00781 {
00782 session->verbose = enabled;
00783 }
00784
00793 void nu_client_set_min_delay(nuauth_session_t * session, unsigned int delay)
00794 {
00795 session->min_sleep_delay.tv_sec = delay / 1000;
00796 session->min_sleep_delay.tv_usec = (delay * 1000) % 1000000;
00797 }
00798
00807 void nu_client_set_max_delay(nuauth_session_t * session, unsigned int delay)
00808 {
00809 session->max_sleep_delay.tv_sec = delay / 1000;
00810 session->max_sleep_delay.tv_usec = (delay * 1000) % 1000000;
00811 }
00812
00817 int nu_client_error_init(nuclient_error_t ** err)
00818 {
00819 if (*err != NULL)
00820 return -1;
00821 *err = malloc(sizeof(nuclient_error_t));
00822 if (*err == NULL)
00823 return -1;
00824 return 0;
00825 }
00826
00831 void nu_client_error_destroy(nuclient_error_t * err)
00832 {
00833 if (err != NULL)
00834 free(err);
00835 }
00836
00841 const char *nu_client_strerror(nuauth_session_t * session, nuclient_error_t * err)
00842 {
00843 if (err == NULL) {
00844 return "Error structure was not initialised";
00845 }
00846
00847 switch (err->family) {
00848 case NUSSL_ERR:
00849 if(session == NULL || session->nussl == NULL)
00850 return "NuSSL initialization error.";
00851 return nussl_get_error(session->nussl);
00852 case SASL_ERROR:
00853 return sasl_errstring(err->error, NULL, NULL);
00854 break;
00855 case INTERNAL_ERROR:
00856 switch (err->error) {
00857 case NO_ERR:
00858 return "No error";
00859 case SESSION_NOT_CONNECTED_ERR:
00860 return "Session not connected";
00861 case TIMEOUT_ERR:
00862 return "Connection timeout";
00863 case DNS_RESOLUTION_ERR:
00864 return "DNS resolution error";
00865 case NO_ADDR_ERR:
00866 return "Address not recognized";
00867 case FILE_ACCESS_ERR:
00868 return "File access error";
00869 case CANT_CONNECT_ERR:
00870 return "Connection failed";
00871 case MEMORY_ERR:
00872 return "No more memory";
00873 case TCPTABLE_ERR:
00874 return "Unable to read connection table";
00875 case SEND_ERR:
00876 return "Unable to send packet to nuauth";
00877 case BAD_CREDENTIALS_ERR:
00878 return "Bad credentials";
00879 case BINDING_ERR:
00880 return "Binding (source address) error";
00881 case NUSSL_INIT_ERR:
00882 return "NuSSL initialisation failed.";
00883 default:
00884 return "Unknown internal error code";
00885 }
00886 break;
00887 default:
00888 return "Unknown family error";
00889 }
00890 }
00891
00898 const char *nu_get_version()
00899 {
00900 return NUCLIENT_VERSION;
00901 }
00902
00910 int nu_check_version(const char *version)
00911 {
00912 if (strcmp(NUCLIENT_VERSION, version) == 0)
00913 return 1;
00914 else
00915 return 0;
00916 }
00917