Browse files

Added getpasswd routine for getting a password from the user. A few u…

…pdates to the lib to accomodate clearing the password after we are done with it. Update the fwknop program to reflect/use some of the new functionality.

git-svn-id: file:///home/mbr/svn/fwknop/trunk@59 510a4753-2344-4c79-9c09-4d669213fbeb
  • Loading branch information...
1 parent 06257a9 commit be3bb0762f269639e233f2ecbed21682f6d62b7a Damien Stuart committed Feb 10, 2009
Showing with 253 additions and 62 deletions.
  1. +3 −2 configure.ac
  2. +4 −9 fko/cipher_funcs.c
  3. +4 −6 fko/cipher_funcs.h
  4. +6 −6 fko/fko.h
  5. +1 −1 fko/fko_digest.c
  6. +45 −24 fko/fko_encryption.c
  7. +2 −2 fko/fko_funcs.c
  8. +3 −2 src/Makefile.am
  9. +1 −0 src/config_init.c
  10. +36 −2 src/fwknop.c
  11. +21 −8 src/fwknop_common.h
  12. +94 −0 src/getpasswd.c
  13. +33 −0 src/getpasswd.h
View
5 configure.ac
@@ -31,7 +31,7 @@ AC_PROG_LIBTOOL
# Checks for header files.
#
AC_HEADER_STDC
-AC_CHECK_HEADERS([locale.h stdlib.h string.h sys/time.h unistd.h ctype.h])
+AC_CHECK_HEADERS([ctype.h netinet/in.h stdlib.h string.h strings.h sys/time.h termios.h unistd.h])
# Type checks.
#
@@ -52,7 +52,8 @@ AC_CHECK_SIZEOF(unsigned int)
#
AC_FUNC_MALLOC
AC_FUNC_REALLOC
-AC_CHECK_FUNCS([bzero gettimeofday memmove memset strchr strcspn strdup strndup strrchr strspn])
+AC_FUNC_STAT
+AC_CHECK_FUNCS([bzero gettimeofday memmove memset socket strchr strcspn strdup strncasecmp strndup strrchr strspn])
# Check for gpgme
#AM_PATH_GPGME
View
13 fko/cipher_funcs.c
@@ -72,7 +72,7 @@ get_random_data(unsigned char *data, size_t len)
* the Perl Crypt::CBC module's use of Rijndael.
*/
void
-rij_salt_and_iv(RIJNDAEL_context *ctx, const char *pass, unsigned char *data)
+rij_salt_and_iv(RIJNDAEL_context *ctx, char *pass, unsigned char *data)
{
char pw_buf[16];
unsigned char tmp_buf[64]; /* How big does this need to be? */
@@ -138,7 +138,7 @@ rij_salt_and_iv(RIJNDAEL_context *ctx, const char *pass, unsigned char *data)
/* Initialization entry point.
*/
void
-rijndael_init(RIJNDAEL_context *ctx, const char *pass, unsigned char *data)
+rijndael_init(RIJNDAEL_context *ctx, char *pass, unsigned char *data)
{
/* Use ECB mode to be compatible with the Crypt::CBC perl module.
@@ -158,7 +158,7 @@ rijndael_init(RIJNDAEL_context *ctx, const char *pass, unsigned char *data)
* module would.
*/
size_t
-rij_encrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *out)
+rij_encrypt(unsigned char *in, size_t in_len, char *pass, unsigned char *out)
{
RIJNDAEL_context ctx;
unsigned char plaintext[16];
@@ -212,7 +212,7 @@ rij_encrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *o
/* Decrypt the given data.
*/
size_t
-rij_decrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *out)
+rij_decrypt(unsigned char *in, size_t in_len, char *pass, unsigned char *out)
{
RIJNDAEL_context ctx;
unsigned char plaintext[16];
@@ -274,9 +274,4 @@ rij_decrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *o
return(ondx - out);
}
-/*** These are GPG-specific functions ***/
-
-//--DSS TODO: Finish me
-
-
/***EOF***/
View
10 fko/cipher_funcs.h
@@ -34,14 +34,12 @@
*/
#define PREDICT_ENCSIZE(x) (1+(x>>4)+(x&0xf?1:0))<<4
-size_t rij_encrypt(unsigned char *in, size_t len, const char *key, unsigned char *out);
-size_t rij_decrypt(unsigned char *in, size_t len, const char *key, unsigned char *out);
+size_t rij_encrypt(unsigned char *in, size_t len, char *key, unsigned char *out);
+size_t rij_decrypt(unsigned char *in, size_t len, char *key, unsigned char *out);
#if HAVE_LIBGPGME
-int gpg_encrypt(fko_ctx_t ctx, const char *enc_key);
-//int gpg_encrypt(unsigned char *in, size_t len, const char *signer, const char *recip, unsigned char **out, size_t *out_sz);
-//int gpg_decrypt(unsigned char *in, size_t len, const char *key, unsigned char **out, size_t *out_sz);
-int gpg_decrypt(fko_ctx_t ctx, const char *enc_key, size_t b64_len);
+int gpg_encrypt(fko_ctx_t ctx, char *enc_key);
+int gpg_decrypt(fko_ctx_t ctx, char *dec_key, size_t b64_len);
#endif /* HAVE_LIBGPGME */
#endif /* CIPHER_FUNCS_H */
View
12 fko/fko.h
@@ -46,7 +46,7 @@ typedef enum {
/* Supported digest types...
*/
typedef enum {
- FKO_DIGEST_MD5 = 0,
+ FKO_DIGEST_MD5 = 1,
FKO_DIGEST_SHA1,
FKO_DIGEST_SHA256,
FKO_LAST_DIGEST_TYPE /* Always leave this as the last one */
@@ -55,7 +55,7 @@ typedef enum {
/* Supported encryption types...
*/
typedef enum {
- FKO_ENCRYPTION_RIJNDAEL = 0,
+ FKO_ENCRYPTION_RIJNDAEL = 1,
FKO_ENCRYPTION_GPG,
FKO_LAST_ENCRYPTION_TYPE /* Always leave this as the last one */
} fko_encryption_type_t;
@@ -131,9 +131,9 @@ typedef struct fko_context *fko_ctx_t;
/* General api calls */
int fko_new(fko_ctx_t *ctx);
-int fko_new_with_data(fko_ctx_t *ctx, char *enc_msg, const char *dec_key);
+int fko_new_with_data(fko_ctx_t *ctx, char *enc_msg, char *dec_key);
void fko_destroy(fko_ctx_t ctx);
-int fko_spa_data_final(fko_ctx_t ctx, const char *enc_key);
+int fko_spa_data_final(fko_ctx_t ctx, char *enc_key);
char* fko_get_spa_data(fko_ctx_t ctx);
@@ -155,8 +155,8 @@ const char* fko_errstr(int err_code);
int fko_encode_spa_data(fko_ctx_t ctx);
int fko_decode_spa_data(fko_ctx_t ctx);
-int fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key);
-int fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key);
+int fko_encrypt_spa_data(fko_ctx_t ctx, char *enc_key);
+int fko_decrypt_spa_data(fko_ctx_t ctx, char *dec_key);
char* fko_get_encoded_data(fko_ctx_t ctx);
/* Get context data functions */
View
2 fko/fko_digest.c
@@ -39,7 +39,7 @@ fko_set_spa_digest_type(fko_ctx_t ctx, short digest_type)
if(!CTX_INITIALIZED(ctx))
return(FKO_ERROR_CTX_NOT_INITIALIZED);
- if(digest_type < 0 || digest_type >= FKO_LAST_DIGEST_TYPE)
+ if(digest_type < 1 || digest_type >= FKO_LAST_DIGEST_TYPE)
return(FKO_ERROR_INVALID_DATA);
ctx->digest_type = digest_type;
View
69 fko/fko_encryption.c
@@ -34,10 +34,19 @@
#define B64_RIJNDAEL_SALT "U2FsdGVkX1"
+/* Wipe out the password buffer.
+*/
+void
+wipe_pw(char *pw)
+{
+ if(pw != NULL)
+ bzero(pw, strlen(pw));
+}
+
/* Prep and encrypt using Rijndael
*/
int
-_rijndael_encrypt(fko_ctx_t ctx, const char *enc_key)
+_rijndael_encrypt(fko_ctx_t ctx, char *enc_key)
{
char *plain;
char *b64cipher;
@@ -89,7 +98,7 @@ _rijndael_encrypt(fko_ctx_t ctx, const char *enc_key)
/* Decode, decrypt, and parse SPA data into the context.
*/
int
-_rijndael_decrypt(fko_ctx_t ctx, const char *dec_key, int b64_len)
+_rijndael_decrypt(fko_ctx_t ctx, char *dec_key, int b64_len)
{
char *tbuf;
unsigned char *cipher;
@@ -156,7 +165,7 @@ _rijndael_decrypt(fko_ctx_t ctx, const char *dec_key, int b64_len)
/* Prep and encrypt using gpgme
*/
int
-gpg_encrypt(fko_ctx_t ctx, const char *enc_key)
+gpg_encrypt(fko_ctx_t ctx, char *enc_key)
{
int res;
char *plain;
@@ -221,7 +230,7 @@ gpg_encrypt(fko_ctx_t ctx, const char *enc_key)
/* Prep and encrypt using gpgme
*/
int
-gpg_decrypt(fko_ctx_t ctx, const char *dec_key, size_t b64_len)
+gpg_decrypt(fko_ctx_t ctx, char *dec_key, size_t b64_len)
{
unsigned char *cipher;
size_t cipher_len;
@@ -307,61 +316,68 @@ fko_get_spa_encryption_type(fko_ctx_t ctx)
/* Encrypt the encoded SPA data.
*/
int
-fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key)
+fko_encrypt_spa_data(fko_ctx_t ctx, char *enc_key)
{
int res;
/* Must be initialized
*/
if(!CTX_INITIALIZED(ctx))
- return(FKO_ERROR_CTX_NOT_INITIALIZED);
+ {
+ res = FKO_ERROR_CTX_NOT_INITIALIZED;
+ goto EWIPEOUT;
+ }
/* If there is no encoded data or the SPA data has been modified,
* go ahead and re-encode here.
*/
if(ctx->encoded_msg == NULL || FKO_IS_SPA_DATA_MODIFIED(ctx))
- {
res = fko_encode_spa_data(ctx);
- if(res != FKO_SUCCESS)
- return(res);
- }
-
/* Croak on invalid encoded message as well. At present this is a
* check for a somewhat arbitrary minimum length for the encoded
* data.
*/
if(strlen(ctx->encoded_msg) < MIN_SPA_ENCODED_MSG_SIZE)
- return(FKO_ERROR_MISSING_ENCODED_DATA);
+ {
+ res = FKO_ERROR_MISSING_ENCODED_DATA;
+ goto EWIPEOUT;
+ }
/* Encrypt according to type and return...
*/
if(ctx->encryption_type == FKO_ENCRYPTION_RIJNDAEL)
- return(_rijndael_encrypt(ctx, enc_key));
-
+ res = _rijndael_encrypt(ctx, enc_key);
else if(ctx->encryption_type == FKO_ENCRYPTION_GPG)
#if HAVE_LIBGPGME
- return(gpg_encrypt(ctx, enc_key));
+ res = gpg_encrypt(ctx, enc_key);
#else
- return(FKO_ERROR_UNSUPPORTED_FEATURE);
+ res = FKO_ERROR_UNSUPPORTED_FEATURE;
#endif
-
else
- return(FKO_ERROR_INVALID_ENCRYPTION_TYPE);
+ res = FKO_ERROR_INVALID_ENCRYPTION_TYPE;
+
+EWIPEOUT:
+ wipe_pw(enc_key);
+
+ return(res);
}
/* Decode, decrypt, and parse SPA data into the context.
*/
int
-fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key)
+fko_decrypt_spa_data(fko_ctx_t ctx, char *dec_key)
{
- int b64_len;
+ int b64_len, res;
/* First, make sure we have data to work with.
*/
if(ctx->encrypted_msg == NULL
|| strlen(ctx->encrypted_msg) < MIN_SPA_ENCODED_MSG_SIZE)
- return(FKO_ERROR_INVALID_DATA);
+ {
+ res = FKO_ERROR_INVALID_DATA;
+ goto DWIPEOUT;
+ }
/* Determine type of encryption used. For know, we are using the
* size of the message.
@@ -375,16 +391,21 @@ fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key)
{
ctx->encryption_type = FKO_ENCRYPTION_GPG;
#if HAVE_LIBGPGME
- return(gpg_decrypt(ctx, dec_key, b64_len));
+ res = gpg_decrypt(ctx, dec_key, b64_len);
#else
- return(FKO_ERROR_UNSUPPORTED_FEATURE);
+ res = FKO_ERROR_UNSUPPORTED_FEATURE;
#endif
}
else /* We are assuming the default of Rijndael */
{
ctx->encryption_type = FKO_ENCRYPTION_RIJNDAEL;
- return(_rijndael_decrypt(ctx, dec_key, b64_len));
+ res = _rijndael_decrypt(ctx, dec_key, b64_len);
}
+
+DWIPEOUT:
+ wipe_pw(dec_key);
+
+ return(res);
}
/* Set the GPG recipient key name.
View
4 fko/fko_funcs.c
@@ -148,7 +148,7 @@ fko_new(fko_ctx_t *r_ctx)
* and parsing the provided data into the context data.
*/
int
-fko_new_with_data(fko_ctx_t *r_ctx, char *enc_msg, const char *dec_key)
+fko_new_with_data(fko_ctx_t *r_ctx, char *enc_msg, char *dec_key)
{
fko_ctx_t ctx;
@@ -254,7 +254,7 @@ fko_version(fko_ctx_t ctx)
* set.
*/
int
-fko_spa_data_final(fko_ctx_t ctx, const char *enc_key)
+fko_spa_data_final(fko_ctx_t ctx, char *enc_key)
{
/* Must be initialized
*/
View
5 src/Makefile.am
@@ -1,7 +1,8 @@
bin_PROGRAMS = fwknop
-fwknop_SOURCES = fwknop.c fwknop.h config_init.c config_init.h fwkop_common.h \
- spa_comm.c spa_comm.h utils.c utils.h
+fwknop_SOURCES = fwknop.c fwknop.h config_init.c config_init.h \
+ fwkop_common.h spa_comm.c spa_comm.h utils.c utils.h \
+ getpasswd.c getpasswd.h
fwknop_LDADD = $(top_builddir)/fko/libfko.la
fwknop_CPPFLAGS = -I $(top_srcdir)/fko
View
1 src/config_init.c
@@ -335,6 +335,7 @@ usage(void)
" --gpg-encryption - Use GPG encyrption (default is Rijndael).\n"
" --gpg-recipient-key - Specify the recipient GPG key name or ID.\n"
" --gpg-signer-key - Specify the signer's GPG key name or ID.\n"
+ " --gpg-agent - Use GPG agent if available.\n"
"\n"
);
View
38 src/fwknop.c
@@ -27,12 +27,20 @@
#include "config_init.h"
#include "spa_comm.h"
#include "utils.h"
+#include "getpasswd.h"
+
+/* Used be the getpw function below.
+*/
+#define CRYPT_OP_ENCRYPT 1
+#define CRYPT_OP_DECRYPT 2
+char* getpw(fko_cli_options_t *options, int crypt_op);
int
main(int argc, char **argv)
{
fko_ctx_t ctx, ctx2;
int res;
+ char *pw;
fko_cli_options_t options;
@@ -55,6 +63,12 @@ main(int argc, char **argv)
*/
if(options.use_gpg)
{
+ /* If use-gpg-agent was not specified, then remove the GPG_AGENT_INFO
+ * ENV variable if it exists.
+ */
+ if(!options.use_gpg_agent)
+ unsetenv("GPG_AGENT_INFO");
+
res = fko_set_spa_encryption_type(ctx, FKO_ENCRYPTION_GPG);
if(res != FKO_SUCCESS)
{
@@ -144,7 +158,7 @@ main(int argc, char **argv)
/* Finalize the context data (encrypt and encode the SPA data)
*/
- res = fko_spa_data_final(ctx, FKO_PW);
+ res = fko_spa_data_final(ctx, getpw(&options, CRYPT_OP_ENCRYPT));
if(res != FKO_SUCCESS)
{
fprintf(stderr,
@@ -178,7 +192,8 @@ main(int argc, char **argv)
/* Now we create a new context based on data from the first one.
*/
- res = fko_new_with_data(&ctx2, fko_get_spa_data(ctx), FKO_PW);
+ res = fko_new_with_data(&ctx2, fko_get_spa_data(ctx),
+ getpw(&options, CRYPT_OP_DECRYPT));
if(res != FKO_SUCCESS)
{
fprintf(stderr,
@@ -205,6 +220,25 @@ main(int argc, char **argv)
return(0);
}
+char*
+getpw(fko_cli_options_t *options, int crypt_op)
+{
+ if(options->use_gpg)
+ {
+ return(options->use_gpg_agent ? ""
+ : getpasswd("Enter passphrase for secret key: "));
+ }
+ else
+ {
+ if(crypt_op == CRYPT_OP_ENCRYPT)
+ return(getpasswd("Enter encryption password: "));
+ else if(crypt_op == CRYPT_OP_DECRYPT)
+ return(getpasswd("Enter decryption password: "));
+ else
+ return(getpasswd("Enter password: "));
+ }
+}
+
static void
display_ctx(fko_ctx_t ctx)
{
View
29 src/fwknop_common.h
@@ -28,14 +28,29 @@
/* Common includes for our other fwknop client source files.
*/
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <ctype.h>
#include <sys/types.h>
-#include <netinet/in.h>
+
+#if STDC_HEADERS
+ #include <stdlib.h>
+ #include <string.h>
+#elif HAVE_STRINGS_H
+ #include <strings.h>
+#endif /* STDC_HEADERS*/
+
+#if HAVE_UNISTD_H
+ #include <unistd.h>
+#endif
+
+#if HAVE_NETINET_IN_H
+ #include <netinet/in.h>
+#endif
+
+#include <signal.h>
#include "fko.h"
@@ -55,8 +70,6 @@
/* Other common defines
*/
-#define FKO_PW "BubbaWasHere" //--DSS Temp
-
#define FKO_DEFAULT_PROTO IPPROTO_UDP
#define FKO_DEFAULT_PORT 62201
#define MAX_IP_STR_LEN 16
View
94 src/getpasswd.c
@@ -0,0 +1,94 @@
+/* $Id$
+ *****************************************************************************
+ *
+ * File: getpasswd.c
+ *
+ * Author: Damien S. Stuart
+ *
+ * Purpose: Routines for obtaining a password from a user.
+ *
+ * Copyright (C) 2009 Damien Stuart (dstuart@dstuart.org)
+ *
+ * License (GNU Public License):
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ *****************************************************************************
+*/
+#include <stdio.h>
+#include <signal.h>
+#include <termios.h>
+
+#include "getpasswd.h"
+
+#define MAX_PASS_LEN 128
+
+/* Generic hex dump function.
+*/
+char*
+getpasswd(const char *prompt)
+{
+ static char pwbuf[MAX_PASS_LEN + 1] = {0};
+ char *ptr;
+ sigset_t sig, old_sig;
+ struct termios ts, old_ts;
+ FILE *fp;
+ int c;
+
+ if((fp = fopen(ctermid(NULL), "r+")) == NULL)
+ return(NULL);
+
+ setbuf(fp, NULL);
+
+ /* Setup blocks for SIGINT and SIGTSTP and save the original signal
+ * mask.
+ */
+ sigemptyset(&sig);
+ sigaddset(&sig, SIGINT);
+ sigaddset(&sig, SIGTSTP);
+ sigprocmask(SIG_BLOCK, &sig, &old_sig);
+
+ /* Save current tty state for later restoration after we disable echo
+ * of characters to the tty.
+ */
+ tcgetattr(fileno(fp), &ts);
+ old_ts = ts;
+ ts.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+ tcsetattr(fileno(fp), TCSAFLUSH, &ts);
+
+ fputs(prompt, fp);
+
+ /* Read in the password.
+ */
+ ptr = pwbuf;
+ while((c = getc(fp)) != EOF && c != '\n')
+ if(ptr < &pwbuf[MAX_PASS_LEN])
+ *ptr++ = c;
+
+ /* Null terminate the password.
+ */
+ *ptr = 0;
+
+ /* we can go ahead and echo out a newline.
+ */
+ putc('\n', fp);
+
+ /* Restore our tty state and signal handlers.
+ */
+ tcsetattr(fileno(fp), TCSAFLUSH, &old_ts);
+ sigprocmask(SIG_BLOCK, &old_sig, NULL);
+
+ fclose(fp);
+
+ return(pwbuf);
+}
+
+/***EOF***/
View
33 src/getpasswd.h
@@ -0,0 +1,33 @@
+/*
+ *****************************************************************************
+ *
+ * File: getpasswd.h
+ *
+ * Author: Damien Stuart (dstuart@dstuart.org)
+ *
+ * Purpose: Header file for getpasswd.c.
+ *
+ * Copyright (C) 2009 Damien Stuart (dstuart@dstuart.org)
+ *
+ * License (GNU Public License):
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ *****************************************************************************
+*/
+#ifndef GETPASSWD_H
+#define GETPASSWD_H
+
+/* Prototypes
+*/
+char* getpasswd(const char *prompt);
+
+#endif /* GETPASSWD_H */

0 comments on commit be3bb07

Please sign in to comment.