diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2015-09-17 16:43:10 -0500 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2015-09-17 16:43:10 -0500 |
commit | 640e6672c36985234929fc94a1b8288a82427699 (patch) | |
tree | 94f67bfa64d04e05b55bb115e9cfd23d5e4c7b34 /src | |
parent | a87c27c80800fdd1d5313eb37b4c304615144cfb (diff) | |
download | smartcardauth-640e6672c36985234929fc94a1b8288a82427699.tar.gz smartcardauth-640e6672c36985234929fc94a1b8288a82427699.zip |
v2.0 Release
Use TDE builtins for almost all functions
This package now only provides the initramfs LUKS configuration and related program(s)
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 27 | ||||
-rw-r--r-- | src/cardpincheck.c | 330 | ||||
-rw-r--r-- | src/ckpass.c | 284 | ||||
-rw-r--r-- | src/ckpasswd.c | 368 | ||||
-rw-r--r-- | src/messages.c | 493 | ||||
-rw-r--r-- | src/smartauthmon.cpp | 839 | ||||
-rw-r--r-- | src/xmalloc.c | 163 |
7 files changed, 336 insertions, 2168 deletions
diff --git a/src/Makefile b/src/Makefile index 4addb1c..f0dac07 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,25 +1,10 @@ -all: ckpasswd.o xmalloc.o messages.o ckpass.o ckpasswd smartauthmon +all: cardpincheck.o cardpincheck -ckpass.o: ckpass.c - gcc ckpass.c -c +cardpincheck.o: cardpincheck.c + gcc cardpincheck.c -c -ckpasswd.o: ckpasswd.c - gcc ckpasswd.c -c - -xmalloc.o: xmalloc.c - gcc xmalloc.c -c - -messages.o: messages.c - gcc messages.c -c - -smartauthmon.o: smartauthmon.cpp - g++ -I/usr/include/tqt -I/usr/include/qt3 -I/usr/include/tqt3 smartauthmon.cpp -c - -ckpasswd: ckpasswd.o - gcc ckpasswd.o xmalloc.o messages.o -o ckpasswd -lpam -lcrypt - -smartauthmon: smartauthmon.o ckpass.o - gcc smartauthmon.o ckpass.o xmalloc.o messages.o -o smartauthmon -ltqt -lpam -lcrypt -ltqt-mt -lstdc++ +cardpincheck: cardpincheck.o + gcc cardpincheck.o -o cardpincheck -ldl -lpthread -lgnutls -lcrypto -lpkcs11-helper clean: - rm -f ckpasswd.o xmalloc.o messages.o ckpasswd + rm -f cardpincheck.o cardpincheck diff --git a/src/cardpincheck.c b/src/cardpincheck.c new file mode 100644 index 0000000..c79012b --- /dev/null +++ b/src/cardpincheck.c @@ -0,0 +1,330 @@ +/* Cryptographic card PIN check and RSA decryption utility + * Copyright (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <termios.h> +#include <unistd.h> + +#include <pkcs11-helper-1.0/pkcs11h-certificate.h> +#include <pkcs11-helper-1.0/pkcs11h-openssl.h> + +#define CARD_MAX_LOGIN_RETRY_COUNT 3 + +char has_plymouth = 0; +char use_cached_pin = 0; +char* cached_pin = NULL; + +static PKCS11H_BOOL pkcs_pin_hook(IN void * const global_data, IN void * const user_data, IN const pkcs11h_token_id_t token, IN const unsigned retry, OUT char * const pin, IN const size_t pin_max) { + int pos; + char *line = NULL; + size_t size; + ssize_t read; + + if (use_cached_pin && cached_pin) { + // Copy PIN to buffer + snprintf(pin, pin_max, "%s", cached_pin); + + // Success + return 1; + } + + // Hide input + struct termios oldt; + tcgetattr(STDIN_FILENO, &oldt); + struct termios newt = oldt; + newt.c_lflag &= ~ECHO; + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + + if (has_plymouth) { + char buffer[1024]; + snprintf(buffer, 1024, "plymouth ask-for-password --prompt=\"Please enter the PIN for '%s'\"", token->display); + system(buffer); + } + else { + fprintf(stderr, "Please enter the PIN for '%s'\n", token->display); + } + fflush(stdout); + + read = getline(&line, &size, stdin); + if ((read < 0) || (read >= pin_max)) { + free(line); + + // Abort + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + return 0; + } + else { + // Strip newlines + pos = 0; + while (line[pos] != 0) { + if ((line[pos] == '\n') || (line[pos] == '\r')) { + line[pos] = 0; + break; + } + pos++; + } + + // Copy PIN to cache + if (cached_pin) { + free(cached_pin); + } + cached_pin= malloc(sizeof(char) * pin_max); + snprintf(cached_pin, pin_max, "%s", line); + + // Copy PIN to buffer + snprintf(pin, pin_max, "%s", line); + free(line); + + // Success + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + return 1; + } +} + +static void pkcs_log_hook(IN void * const global_data, IN unsigned flags, IN const char * const format, IN va_list args) { + if (!has_plymouth) { + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + } +} + +int main(int argc, char* argv[]) { + CK_RV rv; + pkcs11h_certificate_id_list_t issuers; + pkcs11h_certificate_id_list_t certs; + + has_plymouth = 0; + const char* with_plymount_var = getenv("HAS_PLYMOUTH"); + if (with_plymount_var && (with_plymount_var[0] == '1')) { + has_plymouth = 1; + } + + if ((argc < 2) || (argv[1][0] == 0)) { + fprintf(stderr, "Usage: ./cardpincheck <opensc provider library> <file to decrypt>\n" + "Example: ./cardpincheck /usr/lib/opensc-pkcs11.so\n"); + return -5; + } + + char* opensc_provider_library = argv[1]; + + char decryption_requested = 0; + char* file_to_decrypt = NULL; + if (argc > 2) { + decryption_requested = 1; + file_to_decrypt = argv[2]; + } + + fprintf(stderr, "Initializing pkcs11-helper\n"); + if ((rv = pkcs11h_initialize()) != CKR_OK) { + fprintf(stderr, "pkcs11h_initialize failed: %s\n", pkcs11h_getMessage(rv)); + return -1; + } + + fprintf(stderr, "Registering pkcs11-helper hooks\n"); + if ((rv = pkcs11h_setLogHook(pkcs_log_hook, NULL)) != CKR_OK) { + fprintf(stderr, "pkcs11h_setLogHook failed: %s\n", pkcs11h_getMessage(rv)); + return -1; + } + pkcs11h_setLogLevel(PKCS11H_LOG_WARN); + // pkcs11h_setLogLevel(PKCS11H_LOG_DEBUG2); + +#if 0 + if ((rv = pkcs11h_setTokenPromptHook(_pkcs11h_hooks_token_prompt, NULL)) != CKR_OK) { + fprintf(stderr, "pkcs11h_setTokenPromptHook failed: %s\n", pkcs11h_getMessage(rv)); + return -1; + } +#endif + + if ((rv = pkcs11h_setMaxLoginRetries(CARD_MAX_LOGIN_RETRY_COUNT)) != CKR_OK) { + fprintf(stderr, "pkcs11h_setMaxLoginRetries failed: %s\n", pkcs11h_getMessage(rv)); + return -1; + } + + if ((rv = pkcs11h_setPINPromptHook(pkcs_pin_hook, NULL)) != CKR_OK) { + fprintf(stderr, "pkcs11h_setPINPromptHook failed: %s\n", pkcs11h_getMessage(rv)); + return -1; + } + + fprintf(stderr, "Adding provider '%s'\n", opensc_provider_library); + if ((rv = pkcs11h_addProvider(opensc_provider_library, opensc_provider_library, FALSE, PKCS11H_PRIVATEMODE_MASK_AUTO, PKCS11H_SLOTEVENT_METHOD_AUTO, 0, FALSE)) != CKR_OK) { + fprintf(stderr, "pkcs11h_addProvider failed: %s\n", pkcs11h_getMessage(rv)); + return -1; + } + + rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, &issuers, &certs); + if ((rv != CKR_OK) || (certs == NULL)) { + fprintf(stderr, "Cannot enumerate certificates: %s\n", pkcs11h_getMessage(rv)); + return -1; + } + + int ret = -1; + int i = 0; + pkcs11h_certificate_id_list_t cert; + pkcs11h_certificate_t certificate = NULL; + RSA* rsa_pubkey = NULL; + for (cert = certs; cert != NULL; cert = cert->next) { + rv = pkcs11h_certificate_create(certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, PKCS11H_PIN_CACHE_INFINITE, &certificate); + if (rv != CKR_OK) { + fprintf(stderr, "Cannot read certificate: %s\n", pkcs11h_getMessage(rv)); + pkcs11h_certificate_freeCertificateId(certs->certificate_id); + ret = -1; + break; + } + + pkcs11h_certificate_freeCertificateId(certs->certificate_id); + + pkcs11h_openssl_session_t openssl_session = NULL; + if ((openssl_session = pkcs11h_openssl_createSession(certificate)) == NULL) { + fprintf(stderr, "Cannot initialize openssl session to retrieve cryptographic objects\n"); + pkcs11h_certificate_freeCertificate(certificate); + ret = -1; + break; + } + + // Get certificate data + X509* x509_local; + x509_local = pkcs11h_openssl_session_getX509(openssl_session); + if (!x509_local) { + fprintf(stderr, "Cannot get X509 object\n"); + ret = -1; + } + + // Extract public key from X509 certificate + EVP_PKEY* x509_pubkey = NULL; + x509_pubkey = X509_get_pubkey(x509_local); + if (x509_pubkey) { + rsa_pubkey = EVP_PKEY_get1_RSA(x509_pubkey); + } + + // Check PIN + rv = pkcs11h_certificate_ensureKeyAccess(certificate); + if (rv != CKR_OK) { + if (rv == CKR_CANCEL) { + ret = -3; + break; + } + else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) { + ret = -2; + break; + } + else { + ret = -2; + break; + } + } + else { + // Success! + ret = 0; + break; + } + + pkcs11h_certificate_freeCertificate(certificate); + certificate = NULL; + + i++; + } + + if (decryption_requested && (ret == 0)) { + // We know the cached PIN is correct; disable any further login prompts + use_cached_pin = 1; + + char abort_decryption = 0; + if (file_to_decrypt) { + long ciphertextfilesize = 0; + FILE *ciphertextfile = fopen(file_to_decrypt, "r"); + if (ciphertextfile) { + fseek(ciphertextfile, 0, SEEK_END); + ciphertextfilesize = ftell(ciphertextfile); + fseek(ciphertextfile, 0, SEEK_SET); + + char* ciphertext = malloc(ciphertextfilesize + 1); + fread(ciphertext, ciphertextfilesize, 1, ciphertextfile); + fclose(ciphertextfile); + + // Verify minimum size + if (ciphertextfilesize < 16) { + fprintf(stderr, "Cannot decrypt: ciphertext too small\n"); + abort_decryption = 1; + } + + // Try to get RSA parameters and verify maximum size + if (rsa_pubkey) { + unsigned int rsa_length = RSA_size(rsa_pubkey); + if (ciphertextfilesize > rsa_length) { + fprintf(stderr, "Cannot decrypt: ciphertext too large\n"); + abort_decryption = 1; + } + } + + if (!abort_decryption) { + // Try decryption + size_t size = 0; + + // Determine output buffer size + rv = pkcs11h_certificate_decryptAny(certificate, CKM_RSA_PKCS, ciphertext, ciphertextfilesize, NULL, &size); + if (rv != CKR_OK) { + fprintf(stderr, "Cannot determine decrypted message length: %s (%d)\n", pkcs11h_getMessage(rv), rv); + if (rv == CKR_CANCEL) { + ret = -1; + abort_decryption = 1; + } + else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) { + ret = -1; + abort_decryption = 1; + } + else { + abort_decryption = 1; + } + } + else { + // Decrypt data + char* plaintext = malloc(size); + rv = pkcs11h_certificate_decryptAny(certificate, CKM_RSA_PKCS, ciphertext, ciphertextfilesize, plaintext, &size); + if (rv != CKR_OK) { + fprintf(stderr, "Cannot decrypt: %s (%d)\n", pkcs11h_getMessage(rv), rv); + if (rv == CKR_CANCEL) { + ret = -1; + abort_decryption = 1; + } + else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) { + ret = -1; + abort_decryption = 1; + } + } + else { + // Write decrypted data to stdout + fwrite(plaintext, sizeof(char), size, stdout); + fflush(stdout); + } + free(plaintext); + } + } + free(ciphertext); + } + } + } + else if (ret == 0) { + printf("%s", cached_pin); + } + + if (certificate) { + pkcs11h_certificate_freeCertificate(certificate); + } + pkcs11h_certificate_freeCertificateIdList(issuers); + + return ret; +} diff --git a/src/ckpass.c b/src/ckpass.c deleted file mode 100644 index 1da83c6..0000000 --- a/src/ckpass.c +++ /dev/null @@ -1,284 +0,0 @@ -/* $Id: ckpasswd.c 7565 2006-08-28 02:42:54Z eagle $ -** -** The default username/password authenticator. -** -** This program is intended to be run by nnrpd and handle usernames and -** passwords. It can authenticate against a regular flat file (the type -** managed by htpasswd), a DBM file, the system password file or shadow file, -** or PAM. -*/ - -/* Used for unused parameters to silence gcc warnings. */ -#define UNUSED __attribute__((__unused__)) - -/* Make available the bool type. */ -#if INN_HAVE_STDBOOL_H -# include <stdbool.h> -#else -# undef true -# undef false -# define true (1) -# define false (0) -# ifndef __cplusplus -# define bool int -# endif -#endif /* INN_HAVE_STDBOOL_H */ - -#include <stdlib.h> -#include <string.h> -#include <crypt.h> -#include <fcntl.h> -#include <pwd.h> -#include <grp.h> - -#define DB_DBM_HSEARCH 1 -#include <db.h> -#define OPT_DBM "d:" - -#if HAVE_GETSPNAM -# include <shadow.h> -# define OPT_SHADOW "s" -#else -# define OPT_SHADOW "" -#endif - -/* The functions are actually macros so that we can pick up the file and line - number information for debugging error messages without the user having to - pass those in every time. */ -#define xcalloc(n, size) x_calloc((n), (size), __FILE__, __LINE__) -#define xmalloc(size) x_malloc((size), __FILE__, __LINE__) -#define xrealloc(p, size) x_realloc((p), (size), __FILE__, __LINE__) -#define xstrdup(p) x_strdup((p), __FILE__, __LINE__) -#define xstrndup(p, size) x_strndup((p), (size), __FILE__, __LINE__) - -#include <security/pam_appl.h> - -/* Holds the authentication information from nnrpd. */ -struct auth_info { - char *username; - char *password; -}; - -/* -** The PAM conversation function. -** -** Since we already have all the information and can't ask the user -** questions, we can't quite follow the real PAM protocol. Instead, we just -** return the password in response to every question that PAM asks. There -** appears to be no generic way to determine whether the message in question -** is indeed asking for the password.... -** -** This function allocates an array of struct pam_response to return to the -** PAM libraries that's never freed. For this program, this isn't much of an -** issue, since it will likely only be called once and then the program will -** exit. This function uses malloc and strdup instead of xmalloc and xstrdup -** intentionally so that the PAM conversation will be closed cleanly if we -** run out of memory rather than simply terminated. -** -** appdata_ptr contains the password we were given. -*/ -static int pass_conv(int num_msg, const struct pam_message **msgm UNUSED, struct pam_response **response, void *appdata_ptr) -{ - int i; - - *response = malloc(num_msg * sizeof(struct pam_response)); - if (*response == NULL) - return PAM_CONV_ERR; - for (i = 0; i < num_msg; i++) { - (*response)[i].resp = strdup((char *)appdata_ptr); - (*response)[i].resp_retcode = 0; - } - return PAM_SUCCESS; -} - - -/* -** Authenticate a user via PAM. -** -** Attempts to authenticate a user with PAM, returning true if the user -** successfully authenticates and false otherwise. Note that this function -** doesn't attempt to handle any remapping of the authenticated user by the -** PAM stack, but just assumes that the authenticated user was the same as -** the username given. -** -** Right now, all failures are handled via die. This may be worth revisiting -** in case we want to try other authentication methods if this fails for a -** reason other than the system not having PAM support. -*/ - -static bool auth_pam(const char *username, char *password) -{ - pam_handle_t *pamh; - struct pam_conv conv; - int status; - - conv.conv = pass_conv; - conv.appdata_ptr = password; - status = pam_start("nnrpd", username, &conv, &pamh); - if (status != PAM_SUCCESS) - die("pam_start failed: %s", pam_strerror(pamh, status)); - status = pam_authenticate(pamh, PAM_SILENT); - if (status != PAM_SUCCESS) - die("pam_authenticate failed: %s", pam_strerror(pamh, status)); - status = pam_acct_mgmt(pamh, PAM_SILENT); - if (status != PAM_SUCCESS) - die("pam_acct_mgmt failed: %s", pam_strerror(pamh, status)); - status = pam_end(pamh, status); - if (status != PAM_SUCCESS) - die("pam_end failed: %s", pam_strerror(pamh, status)); - - /* If we get to here, the user successfully authenticated. */ - return true; -} - - -/* -** Try to get a password out of a dbm file. The dbm file should have the -** username for the key and the crypted password as the value. The crypted -** password, if found, is returned as a newly allocated string; otherwise, -** NULL is returned. -*/ -#if !(defined(HAVE_DBM) || defined(HAVE_BDB_DBM)) -static char * -password_dbm(char *user UNUSED, const char *file UNUSED) -{ - return NULL; -} -#else -static char * -password_dbm(char *name, const char *file) -{ - datum key, value; - DBM *database; - char *password; - - database = dbm_open(file, O_RDONLY, 0600); - if (database == NULL) - return NULL; - key.dptr = name; - key.dsize = strlen(name); - value = dbm_fetch(database, key); - if (value.dptr == NULL) { - dbm_close(database); - return NULL; - } - password = xmalloc(value.dsize + 1); - strlcpy(password, value.dptr, value.dsize + 1); - dbm_close(database); - return password; -} -#endif /* HAVE_DBM || HAVE_BDB_DBM */ - - -/* -** Try to get a password out of the system /etc/shadow file. The crypted -** password, if found, is returned as a newly allocated string; otherwise, -** NULL is returned. -*/ -#if !HAVE_GETSPNAM -static char * -password_shadow(const char *user UNUSED) -{ - return NULL; -} -#else -static char * -password_shadow(const char *user) -{ - struct spwd *spwd; - - spwd = getspnam(user); - if (spwd != NULL) - return xstrdup(spwd->sp_pwdp); - return NULL; -} -#endif /* HAVE_GETSPNAM */ - - -/* -** Try to get a password out of the system password file. The crypted -** password, if found, is returned as a newly allocated string; otherwise, -** NULL is returned. -*/ -static char * -password_system(const char *username) -{ - struct passwd *pwd; - - pwd = getpwnam(username); - if (pwd != NULL) - return xstrdup(pwd->pw_passwd); - return NULL; -} - - -/* -** Try to get the name of a user's primary group out of the system group -** file. The group, if found, is returned as a newly allocated string; -** otherwise, NULL is returned. If the username is not found, NULL is -** returned. -*/ -static char * -group_system(const char *username) -{ - struct passwd *pwd; - struct group *gr; - - pwd = getpwnam(username); - if (pwd == NULL) - return NULL; - gr = getgrgid(pwd->pw_gid); - if (gr == NULL) - return NULL; - return xstrdup(gr->gr_name); -} - - -/* -** Output username (and group, if desired) in correct return format. -*/ -static void -output_user(const char *username, bool wantgroup) -{ - if (wantgroup) { - char *group = group_system(username); - if (group == NULL) - die("group info for user %s not available", username); - printf("User:%s@%s\n", username, group); - } - else - printf("User:%s\n", username); -} - - -/* -** Main routines. -** -** We handle the variences between systems with #if blocks above, so that -** this code can look fairly clean. -*/ - -int -check_password(const char* username, const char* password) -{ - bool wantgroup = false; - struct auth_info *authinfo = NULL; - - authinfo = xmalloc(sizeof(struct auth_info)); - authinfo->username = username; - authinfo->password = password; - - if (auth_pam(authinfo->username, authinfo->password)) { - output_user(authinfo->username, wantgroup); - return 0; - } - password = password_system(authinfo->username); - if (password == NULL) - return 1; - if (strcmp(password, crypt(authinfo->password, password)) != 0) - return 1; - - /* The password matched. */ - output_user(authinfo->username, wantgroup); - return 0; -}
\ No newline at end of file diff --git a/src/ckpasswd.c b/src/ckpasswd.c deleted file mode 100644 index 9dbdbcf..0000000 --- a/src/ckpasswd.c +++ /dev/null @@ -1,368 +0,0 @@ -/* $Id: ckpasswd.c 7565 2006-08-28 02:42:54Z eagle $ -** -** The default username/password authenticator. -** -** This program is intended to be run by nnrpd and handle usernames and -** passwords. It can authenticate against a regular flat file (the type -** managed by htpasswd), a DBM file, the system password file or shadow file, -** or PAM. -*/ - -/* Used for unused parameters to silence gcc warnings. */ -#define UNUSED __attribute__((__unused__)) - -/* Make available the bool type. */ -#if INN_HAVE_STDBOOL_H -# include <stdbool.h> -#else -# undef true -# undef false -# define true (1) -# define false (0) -# ifndef __cplusplus -# define bool int -# endif -#endif /* INN_HAVE_STDBOOL_H */ - -#include <stdlib.h> -#include <string.h> -#include <crypt.h> -#include <fcntl.h> -#include <pwd.h> -#include <grp.h> -#include <getopt.h> - -#define DB_DBM_HSEARCH 1 -#include <db.h> -#define OPT_DBM "d:" - -#if HAVE_GETSPNAM -# include <shadow.h> -# define OPT_SHADOW "s" -#else -# define OPT_SHADOW "" -#endif - -/* The functions are actually macros so that we can pick up the file and line - number information for debugging error messages without the user having to - pass those in every time. */ -#define xcalloc(n, size) x_calloc((n), (size), __FILE__, __LINE__) -#define xmalloc(size) x_malloc((size), __FILE__, __LINE__) -#define xrealloc(p, size) x_realloc((p), (size), __FILE__, __LINE__) -#define xstrdup(p) x_strdup((p), __FILE__, __LINE__) -#define xstrndup(p, size) x_strndup((p), (size), __FILE__, __LINE__) - -#include <security/pam_appl.h> - -/* Holds the authentication information from nnrpd. */ -struct auth_info { - char *username; - char *password; -}; - -/* -** The PAM conversation function. -** -** Since we already have all the information and can't ask the user -** questions, we can't quite follow the real PAM protocol. Instead, we just -** return the password in response to every question that PAM asks. There -** appears to be no generic way to determine whether the message in question -** is indeed asking for the password.... -** -** This function allocates an array of struct pam_response to return to the -** PAM libraries that's never freed. For this program, this isn't much of an -** issue, since it will likely only be called once and then the program will -** exit. This function uses malloc and strdup instead of xmalloc and xstrdup -** intentionally so that the PAM conversation will be closed cleanly if we -** run out of memory rather than simply terminated. -** -** appdata_ptr contains the password we were given. -*/ -static int pass_conv(int num_msg, const struct pam_message **msgm UNUSED, struct pam_response **response, void *appdata_ptr) -{ - int i; - - *response = malloc(num_msg * sizeof(struct pam_response)); - if (*response == NULL) - return PAM_CONV_ERR; - for (i = 0; i < num_msg; i++) { - (*response)[i].resp = strdup((char *)appdata_ptr); - (*response)[i].resp_retcode = 0; - } - return PAM_SUCCESS; -} - - -/* -** Authenticate a user via PAM. -** -** Attempts to authenticate a user with PAM, returning true if the user -** successfully authenticates and false otherwise. Note that this function -** doesn't attempt to handle any remapping of the authenticated user by the -** PAM stack, but just assumes that the authenticated user was the same as -** the username given. -** -** Right now, all failures are handled via die. This may be worth revisiting -** in case we want to try other authentication methods if this fails for a -** reason other than the system not having PAM support. -*/ - -static bool auth_pam(const char *username, char *password) -{ - pam_handle_t *pamh; - struct pam_conv conv; - int status; - - conv.conv = pass_conv; - conv.appdata_ptr = password; - status = pam_start("nnrpd", username, &conv, &pamh); - if (status != PAM_SUCCESS) - die("pam_start failed: %s", pam_strerror(pamh, status)); - status = pam_authenticate(pamh, PAM_SILENT); - if (status != PAM_SUCCESS) - die("pam_authenticate failed: %s", pam_strerror(pamh, status)); - status = pam_acct_mgmt(pamh, PAM_SILENT); - if (status != PAM_SUCCESS) - die("pam_acct_mgmt failed: %s", pam_strerror(pamh, status)); - status = pam_end(pamh, status); - if (status != PAM_SUCCESS) - die("pam_end failed: %s", pam_strerror(pamh, status)); - - /* If we get to here, the user successfully authenticated. */ - return true; -} - - -/* -** Try to get a password out of a dbm file. The dbm file should have the -** username for the key and the crypted password as the value. The crypted -** password, if found, is returned as a newly allocated string; otherwise, -** NULL is returned. -*/ -#if !(defined(HAVE_DBM) || defined(HAVE_BDB_DBM)) -static char * -password_dbm(char *user UNUSED, const char *file UNUSED) -{ - return NULL; -} -#else -static char * -password_dbm(char *name, const char *file) -{ - datum key, value; - DBM *database; - char *password; - - database = dbm_open(file, O_RDONLY, 0600); - if (database == NULL) - return NULL; - key.dptr = name; - key.dsize = strlen(name); - value = dbm_fetch(database, key); - if (value.dptr == NULL) { - dbm_close(database); - return NULL; - } - password = xmalloc(value.dsize + 1); - strlcpy(password, value.dptr, value.dsize + 1); - dbm_close(database); - return password; -} -#endif /* HAVE_DBM || HAVE_BDB_DBM */ - - -/* -** Try to get a password out of the system /etc/shadow file. The crypted -** password, if found, is returned as a newly allocated string; otherwise, -** NULL is returned. -*/ -#if !HAVE_GETSPNAM -static char * -password_shadow(const char *user UNUSED) -{ - return NULL; -} -#else -static char * -password_shadow(const char *user) -{ - struct spwd *spwd; - - spwd = getspnam(user); - if (spwd != NULL) - return xstrdup(spwd->sp_pwdp); - return NULL; -} -#endif /* HAVE_GETSPNAM */ - - -/* -** Try to get a password out of the system password file. The crypted -** password, if found, is returned as a newly allocated string; otherwise, -** NULL is returned. -*/ -static char * -password_system(const char *username) -{ - struct passwd *pwd; - - pwd = getpwnam(username); - if (pwd != NULL) - return xstrdup(pwd->pw_passwd); - return NULL; -} - - -/* -** Try to get the name of a user's primary group out of the system group -** file. The group, if found, is returned as a newly allocated string; -** otherwise, NULL is returned. If the username is not found, NULL is -** returned. -*/ -static char * -group_system(const char *username) -{ - struct passwd *pwd; - struct group *gr; - - pwd = getpwnam(username); - if (pwd == NULL) - return NULL; - gr = getgrgid(pwd->pw_gid); - if (gr == NULL) - return NULL; - return xstrdup(gr->gr_name); -} - - -/* -** Output username (and group, if desired) in correct return format. -*/ -static void -output_user(const char *username, bool wantgroup) -{ - if (wantgroup) { - char *group = group_system(username); - if (group == NULL) - die("group info for user %s not available", username); - printf("User:%s@%s\n", username, group); - } - else - printf("User:%s\n", username); -} - - -/* -** Main routines. -** -** We handle the variences between systems with #if blocks above, so that -** this code can look fairly clean. -*/ - -int -main(int argc, char *argv[]) -{ - enum authtype { AUTH_NONE, AUTH_SHADOW, AUTH_FILE, AUTH_DBM }; - - int opt; - enum authtype type = AUTH_NONE; - bool wantgroup = false; - const char *filename = NULL; - struct auth_info *authinfo = NULL; - char *password = NULL; - - //message_program_name = "ckpasswd"; - - while ((opt = getopt(argc, argv, "gf:u:p:" OPT_DBM OPT_SHADOW)) != -1) { - switch (opt) { - case 'g': - if (type == AUTH_DBM || type == AUTH_FILE) - die("-g option is incompatible with -d or -f"); - wantgroup = true; - break; - case 'd': - if (type != AUTH_NONE) - die("only one of -s, -f, or -d allowed"); - if (wantgroup) - die("-g option is incompatible with -d or -f"); - type = AUTH_DBM; - filename = optarg; - break; - case 'f': - if (type != AUTH_NONE) - die("only one of -s, -f, or -d allowed"); - if (wantgroup) - die("-g option is incompatible with -d or -f"); - type = AUTH_FILE; - filename = optarg; - break; - case 's': - if (type != AUTH_NONE) - die("only one of -s, -f, or -d allowed"); - type = AUTH_SHADOW; - break; - case 'u': - if (authinfo == NULL) { - authinfo = xmalloc(sizeof(struct auth_info)); - authinfo->password = NULL; - } - authinfo->username = optarg; - break; - case 'p': - if (authinfo == NULL) { - authinfo = xmalloc(sizeof(struct auth_info)); - authinfo->username = NULL; - } - authinfo->password = optarg; - break; - default: - exit(1); - } - } - if (argc != optind) - die("extra arguments given"); - if (authinfo != NULL && authinfo->username == NULL) - die("-u option is required if -p option is given"); - if (authinfo != NULL && authinfo->password == NULL) - die("-p option is required if -u option is given"); - -// /* Unless a username or password was given on the command line, assume -// we're being run by nnrpd. */ -// if (authinfo == NULL) -// authinfo = get_auth_info(stdin); -// if (authinfo == NULL) -// die("no authentication information from nnrpd"); -// if (authinfo->username[0] == '\0') -// die("null username"); - - /* Run the appropriate authentication routines. */ - switch (type) { - case AUTH_SHADOW: - password = password_shadow(authinfo->username); - if (password == NULL) - password = password_system(authinfo->username); - break; -// case AUTH_FILE: -// password = password_file(authinfo->username, filename); -// break; - case AUTH_DBM: - password = password_dbm(authinfo->username, filename); - break; - case AUTH_NONE: - if (auth_pam(authinfo->username, authinfo->password)) { - output_user(authinfo->username, wantgroup); - exit(0); - } - password = password_system(authinfo->username); - break; - } - - if (password == NULL) - die("user %s unknown", authinfo->username); - if (strcmp(password, crypt(authinfo->password, password)) != 0) - die("invalid password for user %s", authinfo->username); - - /* The password matched. */ - output_user(authinfo->username, wantgroup); - exit(0); -} diff --git a/src/messages.c b/src/messages.c deleted file mode 100644 index 7a54e0a..0000000 --- a/src/messages.c +++ /dev/null @@ -1,493 +0,0 @@ -/* $Id: messages.c 5496 2002-06-07 13:59:06Z alexk $ -** -** Message and error reporting (possibly fatal). -** -** Usage: -** -** extern int cleanup(void); -** extern void log(int, const char *, va_list, int); -** -** message_fatal_cleanup = cleanup; -** message_program_name = argv[0]; -** -** warn("Something horrible happened at %lu", time); -** syswarn("Couldn't unlink temporary file %s", tmpfile); -** -** die("Something fatal happened at %lu", time); -** sysdie("open of %s failed", filename); -** -** debug("Some debugging message about %s", string); -** trace(TRACE_PROGRAM, "Program trace output"); -** notice("Informational notices"); -** -** message_handlers_warn(1, log); -** warn("This now goes through our log function"); -** -** These functions implement message reporting through user-configurable -** handler functions. debug() only does something if DEBUG is defined, -** trace() supports sending trace messages in one of a number of configurable -** classes of traces so that they can be turned on or off independently, and -** notice() and warn() just output messages as configured. die() similarly -** outputs a message but then exits, normally with a status of 1. -** -** The sys* versions do the same, but append a colon, a space, and the -** results of strerror(errno) to the end of the message. All functions -** accept printf-style formatting strings and arguments. -** -** If message_fatal_cleanup is non-NULL, it is called before exit by die and -** sysdie and its return value is used as the argument to exit. It is a -** pointer to a function taking no arguments and returning an int, and can be -** used to call cleanup functions or to exit in some alternate fashion (such -** as by calling _exit). -** -** If message_program_name is non-NULL, the string it points to, followed by -** a colon and a space, is prepended to all error messages logged through the -** message_log_stdout and message_log_stderr message handlers (the former is -** the default for notice, and the latter is the default for warn and die). -** -** Honoring error_program_name and printing to stderr is just the default -** handler; with message_handlers_* the handlers for any message function can -** be changed. By default, notice prints to stdout, warn and die print to -** stderr, and the others don't do anything at all. These functions take a -** count of handlers and then that many function pointers, each one to a -** function that takes a message length (the number of characters snprintf -** generates given the format and arguments), a format, an argument list as a -** va_list, and the applicable errno value (if any). -*/ - -/* Used for unused parameters to silence gcc warnings. */ -#define UNUSED __attribute__((__unused__)) - -/* Make available the bool type. */ -#if INN_HAVE_STDBOOL_H -# include <stdbool.h> -#else -# undef true -# undef false -# define true (1) -# define false (0) -# ifndef __cplusplus -# define bool int -# endif -#endif /* INN_HAVE_STDBOOL_H */ - -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <stdio.h> -#include <errno.h> -#include <syslog.h> -#include <crypt.h> -#include <fcntl.h> -#include <pwd.h> -#include <grp.h> - -/* The functions are actually macros so that we can pick up the file and line - number information for debugging error messages without the user having to - pass those in every time. */ -#define xcalloc(n, size) x_calloc((n), (size), __FILE__, __LINE__) -#define xmalloc(size) x_malloc((size), __FILE__, __LINE__) -#define xrealloc(p, size) x_realloc((p), (size), __FILE__, __LINE__) -#define xstrdup(p) x_strdup((p), __FILE__, __LINE__) -#define xstrndup(p, size) x_strndup((p), (size), __FILE__, __LINE__) - -/* These are the currently-supported types of traces. */ -enum message_trace { - TRACE_NETWORK, /* Network traffic. */ - TRACE_PROGRAM, /* Stages of program execution. */ - TRACE_ALL /* All traces; this must be last. */ -}; - -/* The reporting functions. The ones prefaced by "sys" add a colon, a space, - and the results of strerror(errno) to the output and are intended for - reporting failures of system calls. */ -extern void trace(enum message_trace, const char *, ...) - __attribute__((__format__(printf, 2, 3))); -extern void notice(const char *, ...) - __attribute__((__format__(printf, 1, 2))); -extern void sysnotice(const char *, ...) - __attribute__((__format__(printf, 1, 2))); -extern void warn(const char *, ...) - __attribute__((__format__(printf, 1, 2))); -extern void syswarn(const char *, ...) - __attribute__((__format__(printf, 1, 2))); -extern void die(const char *, ...) - __attribute__((__noreturn__, __format__(printf, 1, 2))); -extern void sysdie(const char *, ...) - __attribute__((__noreturn__, __format__(printf, 1, 2))); - -/* Debug is handled specially, since we want to make the code disappear - completely unless we're built with -DDEBUG. We can only do that with - support for variadic macros, though; otherwise, the function just won't do - anything. */ -#if !defined(DEBUG) && (INN_HAVE_C99_VAMACROS || INN_HAVE_GNU_VAMACROS) -# if INN_HAVE_C99_VAMACROS -# define debug(format, ...) /* empty */ -# elif INN_HAVE_GNU_VAMACROS -# define debug(format, args...) /* empty */ -# endif -#else -extern void debug(const char *, ...) - __attribute__((__format__(printf, 1, 2))); -#endif - -/* Set the handlers for various message functions. All of these functions - take a count of the number of handlers and then function pointers for each - of those handlers. These functions are not thread-safe; they set global - variables. */ -extern void message_handlers_debug(int count, ...); -extern void message_handlers_trace(int count, ...); -extern void message_handlers_notice(int count, ...); -extern void message_handlers_warn(int count, ...); -extern void message_handlers_die(int count, ...); - -/* Enable or disable tracing for particular classes of messages. */ -extern void message_trace_enable(enum message_trace, bool); - -/* Some useful handlers, intended to be passed to message_handlers_*. All - handlers take the length of the formatted message, the format, a variadic - argument list, and the errno setting if any. */ -extern void message_log_stdout(int, const char *, va_list, int); -extern void message_log_stderr(int, const char *, va_list, int); -extern void message_log_syslog_debug(int, const char *, va_list, int); -extern void message_log_syslog_info(int, const char *, va_list, int); -extern void message_log_syslog_notice(int, const char *, va_list, int); -extern void message_log_syslog_warning(int, const char *, va_list, int); -extern void message_log_syslog_err(int, const char *, va_list, int); -extern void message_log_syslog_crit(int, const char *, va_list, int); - -/* The type of a message handler. */ -typedef void (*message_handler_func)(int, const char *, va_list, int); - -/* If non-NULL, called before exit and its return value passed to exit. */ -extern int (*message_fatal_cleanup)(void); - -/* If non-NULL, prepended (followed by ": ") to all messages printed by either - message_log_stdout or message_log_stderr. */ -extern const char *message_program_name; - -/* The default handler lists. */ -static message_handler_func stdout_handlers[2] = { - message_log_stdout, NULL -}; -static message_handler_func stderr_handlers[2] = { - message_log_stderr, NULL -}; - -/* The list of logging functions currently in effect. */ -static message_handler_func *debug_handlers = NULL; -static message_handler_func *trace_handlers = NULL; -static message_handler_func *notice_handlers = stdout_handlers; -static message_handler_func *warn_handlers = stderr_handlers; -static message_handler_func *die_handlers = stderr_handlers; - -/* If non-NULL, called before exit and its return value passed to exit. */ -int (*message_fatal_cleanup)(void) = NULL; - -/* If non-NULL, prepended (followed by ": ") to messages. */ -const char *message_program_name = NULL; - -/* Whether or not we're currently outputting a particular type of trace. */ -static bool tracing[TRACE_ALL] = { false /* false, ... */ }; - - -/* -** Set the handlers for a particular message function. Takes a pointer to -** the handler list, the count of handlers, and the argument list. -*/ -static void -message_handlers(message_handler_func **list, int count, va_list args) -{ - int i; - - if (*list != stdout_handlers && *list != stderr_handlers) - free(*list); - *list = xmalloc(sizeof(message_handler_func) * (count + 1)); - for (i = 0; i < count; i++) - (*list)[i] = (message_handler_func) va_arg(args, message_handler_func); - (*list)[count] = NULL; -} - - -/* -** There's no good way of writing these handlers without a bunch of code -** duplication since we can't assume variadic macros, but I can at least make -** it easier to write and keep them consistent. -*/ -#define HANDLER_FUNCTION(type) \ - void \ - message_handlers_ ## type(int count, ...) \ - { \ - va_list args; \ - \ - va_start(args, count); \ - message_handlers(& type ## _handlers, count, args); \ - va_end(args); \ - } -HANDLER_FUNCTION(debug) -HANDLER_FUNCTION(trace) -HANDLER_FUNCTION(notice) -HANDLER_FUNCTION(warn) -HANDLER_FUNCTION(die) - - -/* -** Print a message to stdout, supporting message_program_name. -*/ -void -message_log_stdout(int len UNUSED, const char *fmt, va_list args, int err) -{ - if (message_program_name != NULL) - fprintf(stdout, "%s: ", message_program_name); - vfprintf(stdout, fmt, args); - if (err) - fprintf(stdout, ": %s", strerror(err)); - fprintf(stdout, "\n"); -} - - -/* -** Print a message to stderr, supporting message_program_name. Also flush -** stdout so that errors and regular output occur in the right order. -*/ -void -message_log_stderr(int len UNUSED, const char *fmt, va_list args, int err) -{ - fflush(stdout); - if (message_program_name != NULL) - fprintf(stderr, "%s: ", message_program_name); - vfprintf(stderr, fmt, args); - if (err) - fprintf(stderr, ": %s", strerror(err)); - fprintf(stderr, "\n"); -} - - -/* -** Log a message to syslog. This is a helper function used to implement all -** of the syslog message log handlers. It takes the same arguments as a -** regular message handler function but with an additional priority -** argument. -*/ -static void -message_log_syslog(int pri, int len, const char *fmt, va_list args, int err) -{ - char *buffer; - - buffer = malloc(len + 1); - if (buffer == NULL) { - fprintf(stderr, "failed to malloc %u bytes at %s line %d: %s", - len + 1, __FILE__, __LINE__, strerror(errno)); - exit(message_fatal_cleanup ? (*message_fatal_cleanup)() : 1); - } - vsnprintf(buffer, len + 1, fmt, args); - syslog(pri, err ? "%s: %m" : "%s", buffer); - free(buffer); -} - - -/* -** Do the same sort of wrapper to generate all of the separate syslog logging -** functions. -*/ -#define SYSLOG_FUNCTION(name, type) \ - void \ - message_log_syslog_ ## name(int l, const char *f, va_list a, int e) \ - { \ - message_log_syslog(LOG_ ## type, l, f, a, e); \ - } -SYSLOG_FUNCTION(debug, DEBUG) -SYSLOG_FUNCTION(info, INFO) -SYSLOG_FUNCTION(notice, NOTICE) -SYSLOG_FUNCTION(warning, WARNING) -SYSLOG_FUNCTION(err, ERR) -SYSLOG_FUNCTION(crit, CRIT) - - -/* -** Enable or disable tracing for particular classes of messages. -*/ -void -message_trace_enable(enum message_trace type, bool enable) -{ - if (type > TRACE_ALL) - return; - if (type == TRACE_ALL) { - int i; - - for (i = 0; i < TRACE_ALL; i++) - tracing[i] = enable; - } else { - tracing[type] = enable; - } -} - - -/* -** All of the message handlers. There's a lot of code duplication here too, -** but each one is still *slightly* different and va_start has to be called -** multiple times, so it's hard to get rid of the duplication. -*/ - -#ifdef DEBUG -void -debug(const char *format, ...) -{ - va_list args; - message_handler_func *log; - int length; - - if (debug_handlers == NULL) - return; - va_start(args, format); - length = vsnprintf(NULL, 0, format, args); - va_end(args); - if (length < 0) - return; - for (log = debug_handlers; *log != NULL; log++) { - va_start(args, format); - (**log)(length, format, args, 0); - va_end(args); - } -} -#elif !INN_HAVE_C99_VAMACROS && !INN_HAVE_GNU_VAMACROS -void debug(const char *format UNUSED, ...) { } -#endif - -void -trace(enum message_trace type, const char *format, ...) -{ - va_list args; - message_handler_func *log; - int length; - - if (trace_handlers == NULL || !tracing[type]) - return; - va_start(args, format); - length = vsnprintf(NULL, 0, format, args); - va_end(args); - if (length < 0) - return; - for (log = trace_handlers; *log != NULL; log++) { - va_start(args, format); - (**log)(length, format, args, 0); - va_end(args); - } -} - -void -notice(const char *format, ...) -{ - va_list args; - message_handler_func *log; - int length; - - va_start(args, format); - length = vsnprintf(NULL, 0, format, args); - va_end(args); - if (length < 0) - return; - for (log = notice_handlers; *log != NULL; log++) { - va_start(args, format); - (**log)(length, format, args, 0); - va_end(args); - } -} - -void -sysnotice(const char *format, ...) -{ - va_list args; - message_handler_func *log; - int length; - int error = errno; - - va_start(args, format); - length = vsnprintf(NULL, 0, format, args); - va_end(args); - if (length < 0) - return; - for (log = notice_handlers; *log != NULL; log++) { - va_start(args, format); - (**log)(length, format, args, error); - va_end(args); - } -} - -void -warn(const char *format, ...) -{ - va_list args; - message_handler_func *log; - int length; - - va_start(args, format); - length = vsnprintf(NULL, 0, format, args); - va_end(args); - if (length < 0) - return; - for (log = warn_handlers; *log != NULL; log++) { - va_start(args, format); - (**log)(length, format, args, 0); - va_end(args); - } -} - -void -syswarn(const char *format, ...) -{ - va_list args; - message_handler_func *log; - int length; - int error = errno; - - va_start(args, format); - length = vsnprintf(NULL, 0, format, args); - va_end(args); - if (length < 0) - return; - for (log = warn_handlers; *log != NULL; log++) { - va_start(args, format); - (**log)(length, format, args, error); - va_end(args); - } -} - -void -die(const char *format, ...) -{ - va_list args; - message_handler_func *log; - int length; - - va_start(args, format); - length = vsnprintf(NULL, 0, format, args); - va_end(args); - if (length >= 0) - for (log = die_handlers; *log != NULL; log++) { - va_start(args, format); - (**log)(length, format, args, 0); - va_end(args); - } - exit(message_fatal_cleanup ? (*message_fatal_cleanup)() : 1); -} - -void -sysdie(const char *format, ...) -{ - va_list args; - message_handler_func *log; - int length; - int error = errno; - - va_start(args, format); - length = vsnprintf(NULL, 0, format, args); - va_end(args); - if (length >= 0) - for (log = die_handlers; *log != NULL; log++) { - va_start(args, format); - (**log)(length, format, args, error); - va_end(args); - } - exit(message_fatal_cleanup ? (*message_fatal_cleanup)() : 1); -} diff --git a/src/smartauthmon.cpp b/src/smartauthmon.cpp deleted file mode 100644 index b83c402..0000000 --- a/src/smartauthmon.cpp +++ /dev/null @@ -1,839 +0,0 @@ -/* Smart Card TDE Authentication Script (c) 2010-2011 Timothy Pearson - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#define _XOPEN_SOURCE 500 -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <dirent.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/select.h> -#include <sys/time.h> -#include <termios.h> -#include <signal.h> -#include <ftw.h> - -#include <tqdir.h> -#include <tqstring.h> -#include <tqstringlist.h> - -// Maximum number of virtual terminals on this system -#define MAXIMUM_VTS 49 - -// The [secure] temporary directory for authentication -#define SECURE_DIRECTORY_PATH "/tmp/smartauth" - -// The Trinity binary directory -#define TRINITY_BIN_PREFIX "/opt/trinity/bin/" - -// Some internal constants -#define CREATE_LIFE_CYCLE "01" - -#define TDM_CONTROL_FIFO_DIR "/tmp/tdesocket-global/tdm" -#define TDM_CONTROL_FIFO_FILE "/tmp/tdesocket-global/tdm/tdmctl-%1" -#define TDM_CONTROL_FIFO_SAK_FILE "/tmp/tdesocket-global/tdm/tdmctl-sak-%1" - -// In ckpass.o -extern "C" { - int check_password(const char* username, const char* password); -} - -static TQString secure_directory; -static TQString command_mode; -static TQString select_file; -static TQString read_binary; -static TQString update_binary; -static TQString delete_file; -static TQString get_challenge; -static TQString external_auth; -static TQString activate_file; - -static TQString hexidecimal_key; - -static TQString darray[MAXIMUM_VTS]; - -static FILE* opensc_explorer_file; - -struct sigaction usr_action; -sigset_t block_mask; - -void handle_sigpipe(int sig) -{ - int uidnum; - if (sig == SIGPIPE) { - printf("Got SIGPIPE!\n"); fflush(stdout); - } -} - -TQString readfile(const char * filename) { - FILE *fp; - long len; - char *buf; - fp=fopen(filename, "rb"); - if (fp == NULL) { - printf("[WARNING] Unable to read from file %s\n", filename); fflush(stdout); - return TQString(); - } - fseek(fp,0,SEEK_END); // Seek to end - len=ftell(fp); // Get position at end (length) - fseek(fp,0,SEEK_SET); // Seek to beginning - buf=(char *)malloc(len+1); // Malloc the buffer - fread(buf,len,1,fp); // Read file - fclose(fp); - buf[len]=0; - TQString contents(buf); - free(buf); // Free the buffer - return contents; -} - -int writefile(const char * filename, TQString contents) { - int fp; - long len; - char *buf; - fp=open(filename, O_WRONLY | O_NONBLOCK); - if (fp < 0) { - printf("[WARNING] Unable to open file %s for writing\n", filename); fflush(stdout); - return -1; - } - int retcode = write(fp, contents.ascii(), contents.length()); - close(fp); - return retcode; -} - -TQString exec(const char * cmd) { - TQString bashcommand = cmd; - bashcommand = bashcommand.replace("\"", "\\\""); - bashcommand = TQString("/bin/bash -c \"%1\"").arg(bashcommand); - FILE* pipe = popen(bashcommand.ascii(), "r"); - if (!pipe) return "ERROR"; - char buffer[128]; - TQString result = ""; - while(!feof(pipe)) { - if(fgets(buffer, 128, pipe) != NULL) { - result += buffer; - } - } - pclose(pipe); - result.remove(result.length(), 1); - return result; -} - -int systemexec(const char * cmd) { - TQString bashcommand = cmd; - bashcommand = bashcommand.replace("\"", "\\\""); - bashcommand = TQString("/bin/bash -c \"%1\"").arg(bashcommand); - return system(bashcommand.ascii()) >> 8; -} - -TQString execret(const char * cmd, int * retcode) { - TQString bashcommand = cmd; - bashcommand = bashcommand.replace("\"", "\\\""); - bashcommand = TQString("/bin/bash -c \"%1\"").arg(bashcommand); - FILE* pipe = popen(bashcommand.ascii(), "r"); - if (!pipe) return "ERROR"; - char buffer[128]; - TQString result = ""; - while(!feof(pipe)) { - if(fgets(buffer, 128, pipe) != NULL) { - result += buffer; - } - } - *retcode = pclose(pipe) >> 8; - result.remove(result.length(), 1); - return result; -} - -int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) -{ - int rv = remove(fpath); - - if (rv) - perror(fpath); - - return rv; -} - -int rmrf(const char *path) -{ - return nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS); -} - -TQString get_file(TQString prefix, TQString mode) { - if (command_mode == "acos") { - // Select EF prefix under DF 1000 - systemexec((TQString("echo \"%1 %2\" > %3/query").arg(select_file).arg(prefix).arg(secure_directory)).ascii()); - systemexec((TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory)).ascii()); -// printf("[DEBUG 100.0] %s\n", readfile((TQString("%1/response2").arg(secure_directory))).ascii()); fflush(stdout); - - // Read binary - systemexec((TQString("echo \"%1\" > %2/query").arg(read_binary).arg(secure_directory)).ascii()); - systemexec((TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory)).ascii()); - TQString authokresponse="90 00 : Normal processing"; - TQString response1 = exec((TQString("cat %1/response2 | grep \"%2\"").arg(secure_directory).arg(authokresponse)).ascii()); - if (response1 != "") { - systemexec((TQString("cat %1/response2 | tr -d '\n' > %2/response4").arg(secure_directory).arg(secure_directory)).ascii()); - TQString stringtoreplace="Using T=0 protocol00 B0 00 00 FF> 00 B0 00 00 FF< "; - TQString newstring=""; - systemexec((TQString("sed -i \"s#%1#%2#g\" %3/response4").arg(stringtoreplace).arg(newstring).arg(secure_directory)).ascii()); - stringtoreplace=" 90 00 : Normal processing."; - newstring=""; - systemexec((TQString("sed -i \"s#%1#%2#g\" %3/response4").arg(stringtoreplace).arg(newstring).arg(secure_directory)).ascii()); - if (mode == "text") { - stringtoreplace=" 00"; - newstring=""; - systemexec((TQString("sed -i \"s#%1#%2#g\" %3/response4").arg(stringtoreplace).arg(newstring).arg(secure_directory)).ascii()); - } -// printf("[DEBUG 100.1] %s\n", readfile((TQString("%1/response4").arg(secure_directory))).ascii()); fflush(stdout); - unlink((TQString("%1/lukskey").arg(secure_directory)).ascii()); - systemexec((TQString("xxd -r -p %1/response4 %2/lukskey").arg(secure_directory).arg(secure_directory)).ascii()); - return(TQString("%1/lukskey").arg(secure_directory)); - } - } - - if (command_mode == "cryptoflex") { - TQString file = TQString(prefix).replace(' ', ""); - unlink((TQString("3F00_%1").arg(file)).ascii()); -// systemexec((TQString("echo \"get %1\" | opensc-explorer").arg(file)).ascii()); - fputs((TQString("get %1\n").arg(file)).ascii(), opensc_explorer_file); - fflush(opensc_explorer_file); - int j; - // Wait up to 2 seconds for the file to be written - for (j=0;j<200;j++) { - FILE* fp1 = fopen((TQString("3F00_%1").arg(file)).ascii(), "r"); - if (fp1) { - // file exists - fclose(fp1); - break; - } - usleep(10000); - } - usleep(100000); // [FIXME] Here I assume that the entire file will be written (after it was created) within 100us. This may not be correct in all cases! - return TQString("3F00_%1").arg(file); - } -} - -void createfile(TQString prefix, TQString mode) -{ - if (command_mode == "cryptoflex") { - // Create transparent file with permissions: - // delete, terminate, activate, deactivate, update, read for Key 1 and Key 2 only - systemexec((TQString("echo \"F0 E0 00 FF 10 FF FF 00 %1 %2 01 3F 44 FF 44 01 03 11 FF 11\" > %3/query").arg(prefix).arg(mode).arg(secure_directory)).ascii()); - systemexec((TQString("scriptor %1/query 1> %2/response2 2>/dev/null").arg(secure_directory).arg(secure_directory)).ascii()); - } - - if (command_mode == "acos") { - // Create transparent file with permissions: - // delete, terminate, activate, deactivate, update, read for Key 1, Key 2, and Key 3 only (SE 04) - // created in DF 1000 under MF, SE file is 10FE - // SIZE TRANSPARENT - - systemexec((TQString("echo \"00 E0 00 00 1A 62 18 80 02 00 %1 82 01 01 83 02 %2 8A 01 %3 8C 08 7F 04 04 04 04 04 04 04\" > %4/query").arg(prefix).arg(mode).arg(CREATE_LIFE_CYCLE).arg(secure_directory)).ascii()); - systemexec((TQString("scriptor %1/query 1> %2/response2 2>/dev/null").arg(secure_directory)).ascii()); - printf("[DEBUG 300.0] %s\n", readfile((TQString("%1/response2").arg(secure_directory))).ascii()); fflush(stdout); - } -} - -void update_file(TQString prefix, TQString mode) { - if (command_mode == "acos") { - // Select EF prefix under DF 1000 - systemexec((TQString("echo \"$SELECT_FILE %1\" > %2/query").arg(prefix).arg(secure_directory)).ascii()); - systemexec((TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory)).ascii()); - printf("[DEBUG 200.0] %s\n", readfile((TQString("%1/response2").arg(secure_directory))).ascii()); fflush(stdout); - - // Update existing file - // Zero pad input file - systemexec((TQString("dd if=/dev/zero of=%1/response2 bs=1 count=255 2>/dev/null 1>/dev/null").arg(secure_directory)).ascii()); - systemexec((TQString("dd if=%1 of=%2/response2 bs=1 count=255 conv=notrunc 2>/dev/null 1>/dev/null").arg(mode).arg(secure_directory)).ascii()); - - // Truncate to 255 bytes and expand to standard hex listing format - systemexec((TQString("xxd -l 255 -ps -c 1 %1/response2 > %2/response").arg(secure_directory).arg(secure_directory)).ascii()); - systemexec((TQString("cat %1/response | tr '\n' ' ' > %1/hexready").arg(secure_directory)).ascii()); - TQString hexready = readfile((TQString("%1/hexready").arg(secure_directory)).ascii()); - systemexec((TQString("echo \"%1 %2\" > %3/query").arg(update_binary).arg(hexready).arg(secure_directory)).ascii()); - systemexec((TQString("scriptor %1/query 1> %2/response2 2>/dev/null").arg(secure_directory).arg(secure_directory)).ascii()); - printf("[DEBUG 200.1] %s\n", readfile((TQString("%1/response2").arg(secure_directory))).ascii()); fflush(stdout); - } - - if (command_mode == "cryptoflex") { - // Delete old file - systemexec((TQString("echo \"%1 $1\" > %2/query").arg(delete_file).arg(secure_directory)).ascii()); - systemexec((TQString("scriptor %1/query 1> %2/response2 2>/dev/null").arg(secure_directory).arg(secure_directory)).ascii()); - printf("[DEBUG 200.2] %s\n", readfile((TQString("%1/response2").arg(secure_directory))).ascii()); fflush(stdout); - - // Create new file - createfile("FF", prefix); - TQString file = TQString(prefix).replace(' ', ""); - systemexec((TQString("echo \"put %1 %2\" | opensc-explorer").arg(file).arg(mode)).ascii()); - } -} - -int main (int argc, char *argv[]) -{ - TQString smartcard_username; - TQString oldsmartcard_username; - TQString smartcard_password; - TQString smartcard_slave; - TQString lverify; - TQString cverify; - TQString udisplay; - TQString newdisplay; - TQString logouttest; - TQString blankresult; - TQString smartcard_minutes_raw; - - int timer; - int smartcard_minutes; - int internet_minutes; - int newdisplayint; - - printf("[DEBUG 390.0] Starting up\n"); fflush(stdout); - - // Initialize signal handlers - sigfillset(&block_mask); - usr_action.sa_handler = handle_sigpipe; - usr_action.sa_mask = block_mask; - usr_action.sa_flags = 0; - sigaction(SIGPIPE, &usr_action, NULL); - - // Create the secure directory and lock it down - secure_directory = SECURE_DIRECTORY_PATH; - rmrf(secure_directory.ascii()); - mkdir(secure_directory.ascii(), 600); - chown(secure_directory.ascii(), 0, 0); - chmod(secure_directory.ascii(), 600); - secure_directory=exec("mktemp " SECURE_DIRECTORY_PATH "/smartauthmon.XXXXXXXXXX"); - secure_directory.replace('\n', ""); - rmrf(secure_directory.ascii()); - mkdir(secure_directory.ascii(), 600); - chown(secure_directory.ascii(), 0, 0); - chmod(secure_directory.ascii(), 600); - - // Terminate old pcscd process from initrd - system("killall -9 pcscd"); - - // See if required programs are installed - TQString scriptor = exec("whereis scriptor"); - if ( scriptor == "scriptor:" ) { - printf("ERROR: scriptor is not installed! This program cannot continue!\n"); fflush(stdout); - return 1; - } - TQString opensc = exec("whereis opensc-explorer"); - if ( opensc == "opensc-explorer:" ) { - printf("ERROR: opensc-explorer is not installed! This program cannot continue!\n"); fflush(stdout); - return 1; - } - - printf("[DEBUG 390.2] Reading keys\n"); fflush(stdout); - - // Read hexidecimal_key from the system crypto files - FILE* fpkey = fopen("/etc/smartauth/smartauthmon.key", "rb"); - if (fpkey == NULL) { - printf("Smart card login has been disabled. Exiting...\n"); fflush(stdout); - return 1; - } - else { - fclose(fpkey); - } - hexidecimal_key = readfile("/etc/smartauth/smartauthmon.key"); - hexidecimal_key.replace('\n', ""); - - oldsmartcard_username=""; - printf("[DEBUG 400.0] Ready...\n"); fflush(stdout); - while (1) { - sleep(1); - int output = systemexec("echo \"exit\" | timeout 1 scriptor 2>/dev/null 1>/dev/null"); - if (output == 0) { - printf("[DEBUG 400.1] Card inserted!\n"); fflush(stdout); - systemexec("echo \"TAuthenticating SmartCard...\" > /tmp/tdesocket-global/kdesktoplockcontrol &"); - - // Get card ATR - systemexec((TQString("echo \"RESET\" > %1/query").arg(secure_directory)).ascii()); - systemexec((TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory)).ascii()); - TQString authokresponse="OK: "; - TQString response1 = exec((TQString("cat %1/response2 | grep \"%2\"").arg(secure_directory).arg(authokresponse)).ascii()); - if (response1 != "") { - systemexec((TQString("cat %1/response2 | tr -d '\n' > %2/response4").arg(secure_directory).arg(secure_directory)).ascii()); - TQString stringtoreplace="Using T=0 protocolRESET> RESET< OK: "; - TQString newstring=""; - systemexec((TQString("sed -i \"s#%1#%2#g\" %3/response4").arg(stringtoreplace).arg(newstring).arg(secure_directory)).ascii()); - TQString smartatr = readfile((TQString("%1/response4").arg(secure_directory)).ascii()); - printf("[DEBUG 400.2] Got ATR: %s\n", smartatr.ascii()); fflush(stdout); - if (smartatr == "3B BE 18 00 00 41 05 10 00 00 00 00 00 00 00 00 00 90 00 ") { - printf("[DEBUG 400.3] Detected ACOS5 card\n"); fflush(stdout); - command_mode="acos"; - } - if (smartatr == "3B 02 14 50 ") { - printf("[DEBUG 400.3] Detected Schlumberger CryptoFlex card\n"); fflush(stdout); - command_mode="cryptoflex"; - } - } - else { - printf("[DEBUG 400.3] No card detected!\n"); fflush(stdout); - } - - if (command_mode == "cryptoflex") { - get_challenge="C0 84 00 00 08"; - external_auth="C0 82 00 00 07 01"; - select_file="C0 A4 00 00 02"; - delete_file="F0 E4 00 00 02"; - } - - if (command_mode == "acos") { - get_challenge="00 84 00 00 08"; - external_auth="00 82 00 82 08"; // Key 2 - select_file="00 A4 00 00 02"; - delete_file="00 E4 00 00 00"; - read_binary="00 B0 00 00 FF"; - update_binary="00 D6 00 00 FF"; - activate_file="00 44 00 00 02"; - } - - // Authenticate card - - if (command_mode == "acos") { - // Select MF - systemexec((TQString("echo \"00 A4 00 00 00\" > %1/query").arg(secure_directory)).ascii()); - systemexec((TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory)).ascii()); - printf("[DEBUG 400.4] %s\n", readfile((TQString("%1/response2").arg(secure_directory))).ascii()); fflush(stdout); - - // Select DF 1000 under MF - systemexec((TQString("echo \"%1 10 00\" > %2/query").arg(select_file).arg(secure_directory)).ascii()); - systemexec((TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory)).ascii()); - printf("[DEBUG 400.5] %s\n", readfile((TQString("%1/response2").arg(secure_directory))).ascii()); fflush(stdout); - } - - systemexec((TQString("echo %1 > %2/authscript").arg(get_challenge).arg(secure_directory)).ascii()); - - systemexec((TQString("scriptor %1/authscript | grep 'Normal processing' > %2/challenge").arg(secure_directory).arg(secure_directory)).ascii()); - systemexec((TQString("perl -pi -e 's/ //g' %1/challenge").arg(secure_directory)).ascii()); - systemexec((TQString("perl -pi -e 's/:Normalprocessing.//g' %1/challenge").arg(secure_directory)).ascii()); - systemexec((TQString("perl -pi -e 's/<//g' %1/challenge").arg(secure_directory)).ascii()); - systemexec((TQString("xxd -r -p %1/challenge %2/challenge").arg(secure_directory).arg(secure_directory)).ascii()); - - // Now DES encrypt the challenge - // Later, change the initialization vector to random if possible - - // Create the response from the challenge - systemexec((TQString("openssl des-ecb -in %1/challenge -out %2/response -K %3 -iv 1").arg(secure_directory).arg(secure_directory).arg(hexidecimal_key)).ascii()); - - if (command_mode == "acos") { - // Truncate to 8 bytes - systemexec((TQString("dd if=%1/response of=%2/response2 bs=1 count=8 2>/dev/null 1>/dev/null").arg(secure_directory).arg(secure_directory)).ascii()); - - // Expand to standard hex listing format - systemexec((TQString("xxd -g 1 %1/response2 %2/response").arg(secure_directory).arg(secure_directory)).ascii()); - systemexec((TQString("dd if=%1/response of=%2/response2 bs=1 count=23 skip=9 2>/dev/null 1>/dev/null").arg(secure_directory).arg(secure_directory)).ascii()); - } - - if (command_mode == "cryptoflex") { - // Truncate to 6 bytes - systemexec((TQString("dd if=%1/response of=%2/response2 bs=1 count=6 2>/dev/null 1>/dev/null").arg(secure_directory).arg(secure_directory)).ascii()); - - // Expand to standard hex listing format - systemexec((TQString("xxd -g 1 %1/response2 %2/response").arg(secure_directory).arg(secure_directory)).ascii()); - systemexec((TQString("dd if=%1/response of=%2/response2 bs=1 count=17 skip=9 2>/dev/null 1>/dev/null").arg(secure_directory).arg(secure_directory)).ascii()); - } - - // Assemble the response file - TQString response2 = readfile((TQString("%1/response2").arg(secure_directory)).ascii()); - response1 = TQString("%1 %2").arg(external_auth).arg(response2); - systemexec((TQString("echo %1 > %2/response").arg(response1).arg(secure_directory)).ascii()); - - // Send the response! - systemexec((TQString("scriptor %1/response > %2/response2").arg(secure_directory).arg(secure_directory)).ascii()); - - // Get the result - authokresponse = "< 90 00 : Normal processing"; - response1 = exec((TQString("cat %1/response2 | grep \"%2\"").arg(secure_directory).arg(authokresponse)).ascii()); - printf("[DEBUG 400.6] %s\n", response1.ascii()); fflush(stdout); - if (response1 != "") { - printf("[DEBUG 400.7] Smart card validation successfull!\n"); fflush(stdout); - if (command_mode == "cryptoflex") { - opensc_explorer_file = popen("opensc-explorer 2>/dev/null 1>/dev/null", "w"); - } - // Get username and password - TQString response = get_file("10 02", "text"); - smartcard_username = readfile(response); - smartcard_username = smartcard_username.replace('\n', ""); - unlink(response.ascii()); - response = get_file("10 03", "text"); - smartcard_password = readfile(response.ascii()); - smartcard_password = smartcard_password.replace('\n', ""); - unlink(response.ascii()); - response = get_file("10 04", "text"); - smartcard_slave = readfile(response); - smartcard_slave = smartcard_slave.replace('\n', ""); - unlink(response.ascii()); - if (smartcard_slave == "SLAVE") { - get_file("10 05", "text"); - smartcard_minutes_raw = readfile(response); - smartcard_minutes_raw = smartcard_minutes_raw.replace('\n', ""); - unlink(response.ascii()); - get_file("10 06", "text"); - internet_minutes = readfile(response).toInt(); - unlink(response.ascii()); - } - } - else { - printf("[DEBUG 400.7] This card does not recognize this system!\n"); fflush(stdout); - systemexec("echo \"EInvalid SmartCard Inserted\" > /tmp/tdesocket-global/kdesktoplockcontrol &"); - sleep(1); - smartcard_username=""; - unlink((TQString("%1/password").arg(secure_directory)).ascii()); - smartcard_slave=""; - } - - if (smartcard_slave == "SLAVE") { - if (smartcard_minutes_raw == "") { - smartcard_minutes=1; - } - else { - smartcard_minutes = smartcard_minutes_raw.toInt(); - } - - // Decrement minutes on card - if (smartcard_minutes > 0) { - smartcard_minutes=smartcard_minutes-1; - systemexec((TQString("echo %1 > %2/minutes").arg(smartcard_minutes).arg(secure_directory)).ascii()); - update_file("10 05", TQString("%1/minutes").arg(secure_directory)); - } - - if (smartcard_minutes == 0) { - printf("[DEBUG 400.8] Minutes have been used up!\n"); fflush(stdout); - // Prohibit logon - smartcard_username=""; - unlink((TQString("%1/password").arg(secure_directory)).ascii()); - } - - mkdir("/etc/smartmon", 644); - systemexec((TQString("echo %1 > /etc/smartmon/minutesremaining").arg(smartcard_minutes)).ascii()); - chmod("/etc/smartmon/minutesremaining", 755); - } - - // Initialize variables - int loginok=1; - - // Try to do the authentication - TQString result=""; - int timeout=0; - int errcode=0; - int waserror=0; - int noactivesessions=0; - - result = exec(TRINITY_BIN_PREFIX "tdmctl -g list"); - if (result == "ok") { - noactivesessions=1; - result="okbutempty"; - } - printf("[DEBUG 400.9] %s\n", result.ascii()); fflush(stdout); - TQString resultbkp=result; - - if (errcode == 0) { - // Allow TDM to finish starting - if (waserror == 1) { - sleep(10); - } - - // Zero the desktop array - int index=0; - while (index < MAXIMUM_VTS) { - darray[index]=""; - index++; - } - - if (result != "okbutempty") { - TQStringList sessionList = TQStringList::split('\t', result, false); - for ( TQStringList::Iterator it = sessionList.begin(); it != sessionList.end(); ++it ) { - TQStringList sessionInfoList = TQStringList::split(',', *it, true); - if ((*(sessionInfoList.at(0))).startsWith(":")) { - darray[(*(sessionInfoList.at(0))).mid(1).toInt()] = (*(sessionInfoList.at(2))); - } - } - } - - // See if the desired user is already logged in - index=0; - int foundsession=0; - while (index < MAXIMUM_VTS) { - if (darray[index] == smartcard_username) { - if (darray[index] != "") { - printf("[DEBUG 400.a] Found existing session on desktop: %d\n", index); fflush(stdout); - foundsession=1; - udisplay = TQString(":%1").arg(index); - // Check password - if (check_password(smartcard_username.ascii(), smartcard_password.ascii()) == 0) { - systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface quit\"").arg(smartcard_username).arg(udisplay)).ascii()); - systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface enable false\"").arg(smartcard_username).arg(udisplay)).ascii()); - systemexec((TQString(TRINITY_BIN_PREFIX "tdmctl activate %1").arg(udisplay)).ascii()); - } - else { - systemexec("echo \"EUnauthorized SmartCard Inserted\" > /tmp/tdesocket-global/kdesktoplockcontrol &"); - } - } - else { - printf("[DEBUG 400.b] Username not specified\n"); fflush(stdout); - foundsession=2; - sleep(1); - } - } - index++; - } - - if (foundsession == 0) { - printf("[DEBUG 400.c] Existing session not found, starting new...\n"); fflush(stdout); - - // Get directory listing of tdm control socket directory - // Also start new X server if needed - bool have_valid_display = false; - bool display_has_sak = false; - bool writeerror = false; - newdisplayint = MAXIMUM_VTS+1; - while (have_valid_display == false) { - display_has_sak = false; - writeerror = false; - TQDir dr(TDM_CONTROL_FIFO_DIR); - dr.setFilter( TQDir::System ); - dr.setSorting( TQDir::Name ); - const TQFileInfoList *list = dr.entryInfoList(); - if (list) { - TQFileInfoListIterator it( *list ); - TQFileInfo *fi; - while ( (fi = it.current()) != NULL ) { - bool isint; - int tempdisplayint; - TQString tempdisplaystr; - tempdisplaystr = fi->fileName(); - printf( "%s\n", fi->fileName().latin1() ); fflush(stdout); - if (fi->fileName().contains("tdmctl-sak-")) { - tempdisplaystr = tempdisplaystr.replace("tdmctl-sak-", ""); - tempdisplayint = tempdisplaystr.toInt(&isint); - if (isint) { - if (tempdisplayint < newdisplayint) { - newdisplayint = tempdisplayint; - display_has_sak = true; - } - } - } - else if (fi->fileName().contains("tdmctl-")) { - tempdisplaystr = tempdisplaystr.replace("tdmctl-", ""); - tempdisplayint = tempdisplaystr.toInt(&isint); - if (isint) { - if (tempdisplayint < newdisplayint) { - newdisplayint = tempdisplayint; - display_has_sak = false; - } - } - } - ++it; - } - if (display_has_sak) { - if (writefile(TQString(TDM_CONTROL_FIFO_SAK_FILE).arg(newdisplayint), "CLOSE\n") < 0) { - // Uh oh, something failed... - printf("Unable to write to TDM control socket %s\n", (TQString(TDM_CONTROL_FIFO_SAK_FILE).arg(newdisplayint)).ascii()); fflush(stdout); - unlink((TQString(TDM_CONTROL_FIFO_SAK_FILE).arg(newdisplayint)).ascii()); - writeerror = true; - } - else { - struct stat buffer; - int status = -1; - int timeout_counter = 0; - while ((status != 0) && (timeout_counter < 30)) { - status = stat((TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint)).ascii(), &buffer); - timeout_counter++; - usleep(100000); - } - } - } - else { - // Make sure the control socket is writable - if (writefile(TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint), "PING\n") < 0) { - // Uh oh, something failed... - printf("Unable to write to TDM control socket %s\n", (TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint)).ascii()); fflush(stdout); - unlink((TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint)).ascii()); - writeerror = true; - } - } - if (newdisplayint == (MAXIMUM_VTS+1)) { - writeerror = true; - systemexec(TRINITY_BIN_PREFIX "tdmctl -g reserve"); - usleep(3000000); - } - if (writeerror) - have_valid_display = false; - else - have_valid_display = true; - } - else - { - // TDM is probably not running yet, as its control directory does not exist - // Wait for 10 seconds and try again - usleep(10000000); - } - } - - newdisplay = TQString(":%1").arg(newdisplayint); - printf("[DEBUG 400.f] Logging in on display %s\n", newdisplay.ascii()); fflush(stdout); - - // Construct login string - TQString logincommand = TQString("LOGIN\t%1\t%2\n").arg(smartcard_username).arg(smartcard_password); - if (writefile(TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint), logincommand) < 0) { - // Uh oh, something failed... - printf("Unable to write to TDM control socket %s\n", (TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint)).ascii()); fflush(stdout); - } - - systemexec((TQString(TRINITY_BIN_PREFIX "tdmctl -g activate %1").arg(newdisplay)).ascii()); - udisplay=newdisplay; - } - - if (smartcard_slave == "SLAVE") { - if (smartcard_minutes < 5) { - systemexec((TQString("su %1 -c \"export DISPLAY=%2; zenity --warning --text 'You have less than 5 minutes of computer time remaining' || exit 0\" &").arg(smartcard_username).arg(udisplay)).ascii()); - } - } - - unlink((TQString("%1/password").arg(secure_directory)).ascii()); - - // if (loginok == 1) { - // Wait for SmartCard removal - systemexec("echo \"C\" > /tmp/tdesocket-global/kdesktoplockcontrol &"); - timer=60; - output=0; - - while (output == 0) { - sleep(1); - systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface quit\"").arg(smartcard_username).arg(udisplay)).ascii()); - systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface enable false\"").arg(smartcard_username).arg(udisplay)).ascii()); - output = systemexec("echo \"exit\" | scriptor 2>/dev/null 1>/dev/null"); - if (smartcard_slave == "SLAVE") { - timer--; - if (timer == 0) { - // 60 seconds have passed, decrement minutes on card - smartcard_minutes--; - systemexec((TQString("echo %1 > /etc/smartmon/minutesremaining").arg(smartcard_minutes)).ascii()); - chmod("/etc/smartmon/minutesremaining", 755); - - timer=60; - - systemexec((TQString("echo %1 > %2/minutes").arg(smartcard_minutes).arg(secure_directory)).ascii()); - update_file("10 05", TQString("%1/minutes").arg(secure_directory)); - - if (smartcard_minutes == 0) { - printf("[DEBUG 401.0] Minutes have been used up!\n"); fflush(stdout); - // Prohibit logon - smartcard_username=""; - unlink((TQString("%1/password").arg(secure_directory)).ascii()); - } - - mkdir("/etc/smartmon", 644); - systemexec((TQString("echo %1 > /etc/smartmon/minutesremaining").arg(smartcard_minutes)).ascii()); - chmod("/etc/smartmon/minutesremaining", 755); - - if (smartcard_minutes == 5) { - systemexec((TQString("su %1 -c \"export DISPLAY=%2; zenity --warning --text 'You have less than 5 minutes of computer time remaining' || exit 0\" &").arg(smartcard_username).arg(udisplay)).ascii()); - } - - if (smartcard_minutes == 0) { - printf("[DEBUG 401.1] Minutes have been used up!\n"); fflush(stdout); - printf("[DEBUG 401.2] Beginning logoff process\n"); fflush(stdout); - output=254; - } - } - } - } - - printf("[DEBUG 401.3] Card removed\n"); fflush(stdout); - - // Is the user still logged in? - result="ok"; - timeout=0; - errcode=0; - result = exec(TRINITY_BIN_PREFIX "tdmctl -g list"); - if (result == "ok") { - noactivesessions=1; - result="okbutempty"; - } - printf("[DEBUG 401.4] %s\n", result.ascii()); fflush(stdout); - - // Zero the desktop array - index=0; - while (index < MAXIMUM_VTS) { - darray[index]=""; - index++; - } - - TQStringList sessionList = TQStringList::split('\t', result, false); - for ( TQStringList::Iterator it = sessionList.begin(); it != sessionList.end(); ++it ) { - TQStringList sessionInfoList = TQStringList::split(',', *it, true); - if ((*(sessionInfoList.at(0))).startsWith(":")) { - darray[(*(sessionInfoList.at(0))).mid(1).toInt()] = (*(sessionInfoList.at(2))); - } - } - - // See if the desired user is still logged in - index=0; - foundsession=0; - while (index != MAXIMUM_VTS) { - if (darray[index] == smartcard_username) { - if (darray[index] != "") { - printf("[DEBUG 401.5] Found existing session on desktop: %d\n", index); fflush(stdout); - udisplay = TQString(":%1").arg(index); - foundsession=1; - errcode=1; - timeout=0; - blankresult=""; - while (blankresult != "true") { - systemexec((TQString(TRINITY_BIN_PREFIX "tdmctl -g activate %1").arg(udisplay)).ascii()); - systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface enable true\"").arg(smartcard_username).arg(udisplay)).ascii()); - systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface lock\"").arg(smartcard_username).arg(udisplay)).ascii()); - int retcode; - blankresult = execret(TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface isBlanked\"").arg(smartcard_username).arg(udisplay).ascii(), &retcode); - if (retcode != 0) { - blankresult="true"; - } - blankresult = blankresult.replace('\n', ""); - - logouttest = exec((TQString("echo %1 | grep 'target display has no VT assigned'").arg(blankresult)).ascii()); - if (logouttest != "") { - printf("[DEBUG 401.6] User has logged out\n"); fflush(stdout); - blankresult="true"; - } - } - } - else { - printf("[DEBUG 401.7] Username not specified!\n"); fflush(stdout); - sleep(1); - } - } - index++; - } - // } - } - - if (command_mode == "cryptoflex") { - pclose(opensc_explorer_file); - } - - smartcard_username=""; - unlink("/etc/smartmon/minutesremaining"); - systemexec("echo \"C\" > /tmp/tdesocket-global/kdesktoplockcontrol &"); - } - } -} diff --git a/src/xmalloc.c b/src/xmalloc.c deleted file mode 100644 index 4d00c52..0000000 --- a/src/xmalloc.c +++ /dev/null @@ -1,163 +0,0 @@ -/* $Id: xmalloc.c 5381 2002-03-31 22:35:47Z rra $ -** -** malloc routines with failure handling. -** -** Usage: -** -** extern xmalloc_handler_t memory_error; -** extern const char *string; -** char *buffer; -** -** xmalloc_error_handler = memory_error; -** buffer = xmalloc(1024); -** xrealloc(buffer, 2048); -** free(buffer); -** buffer = xcalloc(1024); -** free(buffer); -** buffer = xstrdup(string); -** free(buffer); -** buffer = xstrndup(string, 25); -** -** xmalloc, xcalloc, xrealloc, and xstrdup behave exactly like their C -** library counterparts without the leading x except that they will never -** return NULL. Instead, on error, they call xmalloc_error_handler, -** passing it the name of the function whose memory allocation failed, the -** amount of the allocation, and the file and line number where the -** allocation function was invoked (from __FILE__ and __LINE__). This -** function may do whatever it wishes, such as some action to free up -** memory or a call to sleep to hope that system resources return. If the -** handler returns, the interrupted memory allocation function will try its -** allocation again (calling the handler again if it still fails). -** -** xstrndup behaves like xstrdup but only copies the given number of -** characters. It allocates an additional byte over its second argument and -** always nul-terminates the string. -** -** The default error handler, if none is set by the caller, prints an error -** message to stderr and exits with exit status 1. An error handler must -** take a const char * (function name), size_t (bytes allocated), const -** char * (file), and int (line). -** -** xmalloc will return a pointer to a valid memory region on an xmalloc of 0 -** bytes, ensuring this by allocating space for one character instead of 0 -** bytes. -** -** The functions defined here are actually x_malloc, x_realloc, etc. The -** header file defines macros named xmalloc, etc. that pass the file name -** and line number to these functions. -*/ - -/* Used for unused parameters to silence gcc warnings. */ -#define UNUSED __attribute__((__unused__)) - -/* Make available the bool type. */ -#if INN_HAVE_STDBOOL_H -# include <stdbool.h> -#else -# undef true -# undef false -# define true (1) -# define false (0) -# ifndef __cplusplus -# define bool int -# endif -#endif /* INN_HAVE_STDBOOL_H */ - -#include <stdlib.h> -#include <string.h> -#include <crypt.h> -#include <fcntl.h> -#include <pwd.h> -#include <grp.h> - -/* Failure handler takes the function, the size, the file, and the line. */ -typedef void (*xmalloc_handler_t)(const char *, size_t, const char *, int); - -/* Assign to this variable to choose a handler other than the default, which - just calls sysdie. */ -extern xmalloc_handler_t xmalloc_error_handler; - -/* The default error handler. */ -void -xmalloc_fail(const char *function, size_t size, const char *file, int line) -{ - sysdie("failed to %s %lu bytes at %s line %d", function, - (unsigned long) size, file, line); -} - -/* Assign to this variable to choose a handler other than the default. */ -xmalloc_handler_t xmalloc_error_handler = xmalloc_fail; - -void * -x_malloc(size_t size, const char *file, int line) -{ - void *p; - size_t real_size; - - real_size = (size > 0) ? size : 1; - p = malloc(real_size); - while (p == NULL) { - (*xmalloc_error_handler)("malloc", size, file, line); - p = malloc(real_size); - } - return p; -} - -void * -x_calloc(size_t n, size_t size, const char *file, int line) -{ - void *p; - - n = (n > 0) ? n : 1; - size = (size > 0) ? size : 1; - p = calloc(n, size); - while (p == NULL) { - (*xmalloc_error_handler)("calloc", n * size, file, line); - p = calloc(n, size); - } - return p; -} - -void * -x_realloc(void *p, size_t size, const char *file, int line) -{ - void *newp; - - newp = realloc(p, size); - while (newp == NULL && size > 0) { - (*xmalloc_error_handler)("realloc", size, file, line); - newp = realloc(p, size); - } - return newp; -} - -char * -x_strdup(const char *s, const char *file, int line) -{ - char *p; - size_t len; - - len = strlen(s) + 1; - p = malloc(len); - while (p == NULL) { - (*xmalloc_error_handler)("strdup", len, file, line); - p = malloc(len); - } - memcpy(p, s, len); - return p; -} - -char * -x_strndup(const char *s, size_t size, const char *file, int line) -{ - char *p; - - p = malloc(size + 1); - while (p == NULL) { - (*xmalloc_error_handler)("strndup", size + 1, file, line); - p = malloc(size + 1); - } - memcpy(p, s, size); - p[size] = '\0'; - return p; -} |