summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-09-17 16:43:10 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-09-17 16:43:10 -0500
commit640e6672c36985234929fc94a1b8288a82427699 (patch)
tree94f67bfa64d04e05b55bb115e9cfd23d5e4c7b34 /src
parenta87c27c80800fdd1d5313eb37b4c304615144cfb (diff)
downloadsmartcardauth-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/Makefile27
-rw-r--r--src/cardpincheck.c330
-rw-r--r--src/ckpass.c284
-rw-r--r--src/ckpasswd.c368
-rw-r--r--src/messages.c493
-rw-r--r--src/smartauthmon.cpp839
-rw-r--r--src/xmalloc.c163
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;
-}