Added getpasswd routine for getting a password from the user. A few updates 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
This commit is contained in:
Damien Stuart
2009-02-10 01:54:07 +00:00
parent 06257a9222
commit be3bb0762f
13 changed files with 253 additions and 62 deletions
+3 -2
View File
@@ -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
+4 -9
View File
@@ -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***/
+4 -6
View File
@@ -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 */
+6 -6
View File
@@ -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 */
+1 -1
View File
@@ -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;
+45 -24
View File
@@ -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.
+2 -2
View File
@@ -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
*/
+3 -2
View File
@@ -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
+1
View File
@@ -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"
);
+36 -2
View File
@@ -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)
{
+21 -8
View File
@@ -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
+94
View File
@@ -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***/
+33
View File
@@ -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 */