From 770aa4e98aa2930e1a309416f0bdc3d037e6e0f7 Mon Sep 17 00:00:00 2001 From: Mike Black W9MDB Date: Fri, 15 Apr 2022 13:21:35 -0500 Subject: [PATCH] Stage 1 rigctld password working using MD5 hash Need to add Stage 2 which will be encryption using the MD5 hash as the key so the secret key nevers gets trasmitted Then need to add a "by connection" capability as password is permanent across connections right now. --- doc/man1/rigctl.1 | 4 + doc/man1/rigctld.1 | 2 +- include/hamlib/rig.h | 7 +- rigs/dummy/netrigctl.c | 5 +- security/Makefile.am | 13 +- security/md5.c | 310 +++++++++++++++++++++++++++++++++++++++++ security/md5.h | 55 ++++++++ security/password.c | 99 +++++++------ src/rig.c | 13 +- tests/rigctl_parse.c | 37 +++-- tests/rigctld.c | 12 +- 11 files changed, 473 insertions(+), 84 deletions(-) create mode 100644 security/md5.c create mode 100644 security/md5.h diff --git a/doc/man1/rigctl.1 b/doc/man1/rigctl.1 index 1f2e73e99..ea865a449 100644 --- a/doc/man1/rigctl.1 +++ b/doc/man1/rigctl.1 @@ -1188,6 +1188,10 @@ Pause for the given whole (integer) number of .RI \(aq Seconds \(aq before sending the next command to the radio. . +.TP +.BR password " \(aq" \fIPassword\fP \(aq +Sends password to rigctld when rigctld has been secured with -A. Must use the 32-char shared secret from rigctld. +. . .SH READLINE . diff --git a/doc/man1/rigctld.1 b/doc/man1/rigctld.1 index 17458b674..a0cee7eb4 100644 --- a/doc/man1/rigctld.1 +++ b/doc/man1/rigctld.1 @@ -359,7 +359,7 @@ option as it generates no output on its own. . .TP .BR \-A ", " \-\-password -Sets password on rigcltd which requires hamlib to use rig_set_paswword and rigctl to use \\password to access rigctld +Sets password on rigctld which requires hamlib to use rig_set_password and rigctl to use \\password to access rigctld. A 32-char shared secret will be displayed to be used on the client side. . .TP .BR \-h ", " \-\-help diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index d5791574e..804b3f12d 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -26,6 +26,9 @@ #define BUILTINFUNC 0 +// Our shared secret password +#define HAMLIB_SECRET_LENGTH 32 + #define TRACE rig_debug(RIG_DEBUG_TRACE,"%s(%d) trace\n", __FILE__, __LINE__) #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) @@ -2041,7 +2044,7 @@ struct rig_caps { // this will be used to check rigcaps structure is compatible with client char *hamlib_check_rig_caps; // a constant value we can check for hamlib integrity int (*get_conf2)(RIG *rig, token_t token, char *val, int val_len); - int (*password)(RIG *rig, const unsigned char *key1, const unsigned char *key2); /*< Send encrypted password if rigctld is secured with -A/--password */ + int (*password)(RIG *rig, const char *key1); /*< Send encrypted password if rigctld is secured with -A/--password */ }; //! @endcond @@ -3379,7 +3382,7 @@ extern HAMLIB_EXPORT(int) hl_usleep(rig_useconds_t msec); extern HAMLIB_EXPORT(int) rig_cookie(RIG *rig, enum cookie_e cookie_cmd, char *cookie, int cookie_len); -extern HAMLIB_EXPORT(int) rig_password(RIG *rig, const unsigned char *key1, const unsigned char *key2); +extern HAMLIB_EXPORT(int) rig_password(RIG *rig, const char *key1); //extern HAMLIB_EXPORT(int) int longlat2locator HAMLIB_PARAMS((double longitude, diff --git a/rigs/dummy/netrigctl.c b/rigs/dummy/netrigctl.c index d38cccb67..d8c55122f 100644 --- a/rigs/dummy/netrigctl.c +++ b/rigs/dummy/netrigctl.c @@ -2630,15 +2630,14 @@ static int netrigctl_power2mW(RIG *rig, unsigned int *mwpower, float power, RETURNFUNC(RIG_OK); } -int netrigctl_password(RIG *rig, const unsigned char *key1, - const unsigned char *key2) +int netrigctl_password(RIG *rig, const char *key1) { char cmdbuf[256]; char buf[BUF_MAX]; int retval; ENTERFUNC; - rig_debug(RIG_DEBUG_VERBOSE, "%s: key1=%s, key2=%s\n", __func__, key1, key2); + rig_debug(RIG_DEBUG_VERBOSE, "%s: key1=%s\n", __func__, key1); SNPRINTF(cmdbuf, sizeof(cmdbuf), "\\password %s\n", key1); retval = netrigctl_transaction(rig, cmdbuf, strlen(cmdbuf), buf); if (retval != RIG_OK) retval = -RIG_EPROTO; diff --git a/security/Makefile.am b/security/Makefile.am index 63d22ac69..0d8444899 100644 --- a/security/Makefile.am +++ b/security/Makefile.am @@ -1,7 +1,14 @@ EXTRA_DIST = sctest.c +security_test_SOURCES = security_test.c aes.h AESStringCrypt.h password.h security.h sha256.h md5.c md5.h + +security_test_LIBS = libsecurity.la +security_test_LDFLAGS = -L. +security_test_CFLAGS = -L. -I. noinst_LTLIBRARIES = libsecurity.la -libsecurity_la_SOURCES = aes.c AESStringCrypt.c password.c security.c sha256.c aes.h AESStringCrypt.h password.h security.h sha256.h -libsecurity_la_CFLAGS = -I$(srcdir) -LDADD = $(top_builddir)/src/libhamlib.la $(top_builddir)/security/libsecurity.la +libsecurity_la_SOURCES = aes.c AESStringCrypt.c password.c security.c sha256.c md5.c +LDADD = $(top_builddir)/src/libhamlib.la +security_test_LDADD = $(LDADD) + +check_PROGRAMS = security_test diff --git a/security/md5.c b/security/md5.c new file mode 100644 index 000000000..9bdba5835 --- /dev/null +++ b/security/md5.c @@ -0,0 +1,310 @@ +#include "md5.h" + +char *make_digest(const unsigned char *digest, int len) /* {{{ */ +{ + char *md5str = (char *) malloc(sizeof(char) * (len * 2 + 1)); + static const char hexits[17] = "0123456789abcdef"; + int i; + + for (i = 0; i < len; i++) + { + md5str[i * 2] = hexits[digest[i] >> 4]; + md5str[(i * 2) + 1] = hexits[digest[i] & 0x0F]; + } + + md5str[len * 2] = '\0'; + return md5str; +} + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +# define SET(n) \ + (*(MD5_u32plus *)&ptr[(n) * 4]) +# define GET(n) \ + SET(n) +#else +# define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +# define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +const void *body(void *ctxBuf, const void *data, size_t size) +{ + MD5_CTX *ctx = (MD5_CTX *)ctxBuf; + const unsigned char *ptr; + MD5_u32plus a, b, c, d; + MD5_u32plus saved_a, saved_b, saved_c, saved_d; + + ptr = (unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do + { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + + /* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + + /* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + + /* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23) + + /* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } + while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +void MD5Init(void *ctxBuf) +{ + MD5_CTX *ctx = (MD5_CTX *)ctxBuf; + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +void MD5Update(void *ctxBuf, const void *data, size_t size) +{ + MD5_CTX *ctx = (MD5_CTX *)ctxBuf; + MD5_u32plus saved_lo; + MD5_u32plus used, free; + + saved_lo = ctx->lo; + + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + { + ctx->hi++; + } + + ctx->hi += size >> 29; + + used = saved_lo & 0x3f; + + if (used) + { + free = 64 - used; + + if (size < free) + { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, free); + data = (unsigned char *)data + free; + size -= free; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) + { + data = body(ctx, data, size & ~(size_t)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +void MD5Final(unsigned char *result, void *ctxBuf) +{ + MD5_CTX *ctx = (MD5_CTX *)ctxBuf; + MD5_u32plus used, free; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + free = 64 - used; + + if (free < 8) + { + memset(&ctx->buffer[used], 0, free); + body(ctx, ctx->buffer, 64); + used = 0; + free = 64; + } + + memset(&ctx->buffer[used], 0, free - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = ctx->lo; + ctx->buffer[57] = ctx->lo >> 8; + ctx->buffer[58] = ctx->lo >> 16; + ctx->buffer[59] = ctx->lo >> 24; + ctx->buffer[60] = ctx->hi; + ctx->buffer[61] = ctx->hi >> 8; + ctx->buffer[62] = ctx->hi >> 16; + ctx->buffer[63] = ctx->hi >> 24; + + body(ctx, ctx->buffer, 64); + + result[0] = ctx->a; + result[1] = ctx->a >> 8; + result[2] = ctx->a >> 16; + result[3] = ctx->a >> 24; + result[4] = ctx->b; + result[5] = ctx->b >> 8; + result[6] = ctx->b >> 16; + result[7] = ctx->b >> 24; + result[8] = ctx->c; + result[9] = ctx->c >> 8; + result[10] = ctx->c >> 16; + result[11] = ctx->c >> 24; + result[12] = ctx->d; + result[13] = ctx->d >> 8; + result[14] = ctx->d >> 16; + result[15] = ctx->d >> 24; + + memset(ctx, 0, sizeof(*ctx)); +} + +unsigned char *make_hash(char *arg) +{ + MD5_CTX context; + static unsigned char digest[65]; + MD5Init(&context); + MD5Update(&context, arg, strlen(arg)); + MD5Final(digest, &context); + return digest; +} + +char *make_md5(char *pass) +{ + unsigned char *hash = make_hash("password"); + char *md5str = make_digest(hash, 16); + return md5str; +} + +//#define TEST +#ifdef TEST +#include +int main() +{ + char *md5str = make_md5("password"); + printf("md5=%s\n", md5str); + return 0; +} +#endif diff --git a/security/md5.h b/security/md5.h new file mode 100644 index 000000000..1e0d90c04 --- /dev/null +++ b/security/md5.h @@ -0,0 +1,55 @@ +#ifndef MD5_h +#define MD5_h + +//#include "Arduino.h" + +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, + * Inc. MD5 Message-Digest Algorithm (RFC 1321). + * + * Written by Solar Designer in 2001, and placed + * in the public domain. There's absolutely no warranty. + * + * This differs from Colin Plumb's older public domain implementation in + * that no 32-bit integer data type is required, there's no compile-time + * endianness configuration, and the function prototypes match OpenSSL's. + * The primary goals are portability and ease of use. + * + * This implementation is meant to be fast, but not as fast as possible. + * Some known optimizations are not included to reduce source code size + * and avoid compile-time configuration. + */ + +/* + * Updated by Scott MacVicar for arduino + * + */ + +#include +#include + +typedef unsigned long MD5_u32plus; + +typedef struct { + MD5_u32plus lo, hi; + MD5_u32plus a, b, c, d; + unsigned char buffer[64]; + MD5_u32plus block[16]; +} MD5_CTX; + +#if 0 +class MD5 +{ +public: + MD5(); + static unsigned char* make_hash(char *arg); + static unsigned char* make_hash(char *arg,size_t size); + static char* make_digest(const unsigned char *digest, int len); + static const void *body(void *ctxBuf, const void *data, size_t size); + static void MD5Init(void *ctxBuf); + static void MD5Final(unsigned char *result, void *ctxBuf); + static void MD5Update(void *ctxBuf, const void *data, size_t size); +}; +#endif + +#endif diff --git a/security/password.c b/security/password.c index e11509295..1fd630f5d 100644 --- a/security/password.c +++ b/security/password.c @@ -21,67 +21,62 @@ */ #include -//#include -//#include +#include +#include #include +#include "hamlib/rig.h" #include "password.h" -#ifdef NOTWORKING -/* - * passwd_to_utf16 - * - * Convert String to UTF-16LE for windows compatibility - */ -int passwd_to_utf16(char *in_passwd, - int length, - int max_length, - char *out_passwd) +#define HAMLIB_SECRET_LENGTH 32 + +extern char *make_md5(char *password); + +// makes a 32-byte secret key from password using MD5 +// yes -- this is security-by-obscurity +// but password hacking software doesn't use this type of logic +// we want a repeatable password that is not subject to "normal" md5 decryption logic +// could use a MAC address to make it more random but making that portable is TBD +HAMLIB_EXPORT(void) rig_password_generate_secret(char *pass, + char result[HAMLIB_SECRET_LENGTH + 1]) { - char *ic_outbuf, - *ic_inbuf; - iconv_t condesc; - size_t ic_inbytesleft, - ic_outbytesleft; + unsigned int product; + char newpass[256]; + product = pass[0]; - ic_inbuf = in_passwd; - ic_inbytesleft = length; - ic_outbytesleft = max_length; - ic_outbuf = out_passwd; - - if ((condesc = iconv_open("UTF-16LE", nl_langinfo(CODESET))) == - (iconv_t)(-1)) + for (int i = 1; pass[i]; ++i) { - perror("Error in iconv_open"); - return -1; + product *= pass[i]; } - if (iconv(condesc, - &ic_inbuf, - &ic_inbytesleft, - &ic_outbuf, - &ic_outbytesleft) == -1) - { - switch (errno) - { - case E2BIG: - fprintf(stderr, "Error: password too long\n"); - iconv_close(condesc); - return -1; - break; + srandom(product); - default: -#if 0 - printf("EILSEQ(%d), EINVAL(%d), %d\n", EILSEQ, EINVAL, errno); -#endif - fprintf(stderr, - "Error: Invalid or incomplete multibyte sequence\n"); - iconv_close(condesc); - return -1; - } - } + snprintf(newpass, sizeof(newpass) - 1, "%s\t%lu\n", pass, random()); + printf("debug=%s\n", newpass); + char *md5str = make_md5(newpass); - iconv_close(condesc); - return (max_length - ic_outbytesleft); + strncpy(result, md5str, HAMLIB_SECRET_LENGTH); + + // now that we have the md5 we'll do the AES256 + + printf("Shared Secret: %s\n", result); + + printf("\nCan be used with rigctl --password [secret]\nOr can be place in ~/.hamlib_settings\n"); +} + +#define TESTPASSWORD +#ifdef TESTPASSWORD +int main(int argc, char *argv[]) +{ + char secret[HAMLIB_SECRET_LENGTH + 1]; + char password[HAMLIB_SECRET_LENGTH + + 1]; // maximum length usable for password too + + // anything longer will not be used to generate the secret + if (argc == 1) { strcpy(password, "testpass"); } + else { strcpy(password, argv[1]); } + + printf("Using password \"%s\" to generate shared key\n", password); + rig_password_generate_secret(password, secret); + return 0; } #endif - diff --git a/src/rig.c b/src/rig.c index 2e8d7aa9c..80c74c51d 100644 --- a/src/rig.c +++ b/src/rig.c @@ -2080,11 +2080,11 @@ int HAMLIB_API rig_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) } } - if (retcode != RIG_OK) - { + if (retcode != RIG_OK) + { rig_debug(RIG_DEBUG_TRACE, "%s: failed set_mode(%s)=%s\n", __func__, rig_strrmode(mode), rigerror(retcode)); - RETURNFUNC(retcode); + RETURNFUNC(retcode); } rig_set_cache_mode(rig, vfo, mode, width); @@ -7108,15 +7108,14 @@ void *async_data_handler(void *arg) } #endif -HAMLIB_EXPORT(int) rig_password(RIG *rig, const unsigned char *key1, - const unsigned char *key2) +HAMLIB_EXPORT(int) rig_password(RIG *rig, const char *key1) { - int retval = -RIG_ENIMPL; + int retval = -RIG_EPROTO; ENTERFUNC; if (rig->caps->password != NULL) { - retval = rig->caps->password(rig, key1, key2); + retval = rig->caps->password(rig, key1); //retval = RIG_OK; } diff --git a/tests/rigctl_parse.c b/tests/rigctl_parse.c index 48535f90a..b89c12480 100644 --- a/tests/rigctl_parse.c +++ b/tests/rigctl_parse.c @@ -96,7 +96,7 @@ extern int read_history(); static int chk_vfo_executed; char rigctld_password[64]; -int is_passwordOK; +int is_passwordOK; int is_rigctld; @@ -245,7 +245,7 @@ declare_proto_rig(get_cache); declare_proto_rig(halt); declare_proto_rig(pause); declare_proto_rig(password); -declare_proto_rig(set_password); +//declare_proto_rig(set_password); declare_proto_rig(set_clock); declare_proto_rig(get_clock); @@ -354,7 +354,7 @@ static struct test_table test_list[] = { 0xf1, "halt", ACTION(halt), ARG_NOVFO }, /* rigctld only--halt the daemon */ { 0x8c, "pause", ACTION(pause), ARG_IN, "Seconds" }, { 0x98, "password", ACTION(password), ARG_IN | ARG_NOVFO, "Password" }, - { 0x99, "set_password", ACTION(set_password), ARG_IN | ARG_NOVFO, "Password" }, +// { 0x99, "set_password", ACTION(set_password), ARG_IN | ARG_NOVFO, "Password" }, { 0xf7, "get_mode_bandwidths", ACTION(get_mode_bandwidths), ARG_IN | ARG_NOVFO, "Mode" }, { 0x00, "", NULL }, }; @@ -1704,10 +1704,13 @@ readline_repeat: { rig_debug(RIG_DEBUG_ERR, "%s: need password=%s for cmd=%s\n", __func__, rigctld_password, cmd_entry->arg1); - return (-RIG_EPROTO); + fflush(fin); + retcode = -RIG_EPROTO; } - retcode = (*cmd_entry->rig_routine)(my_rig, + else + { + retcode = (*cmd_entry->rig_routine)(my_rig, fout, fin, interactive, @@ -1721,6 +1724,7 @@ readline_repeat: p1, p2 ? p2 : "", p3 ? p3 : ""); + } if (retcode == -RIG_EIO) @@ -4934,15 +4938,18 @@ declare_proto_rig(pause) return (RIG_OK); } -int rigctld_password_check(RIG *rig, const unsigned char *key1, - const unsigned char *key2) +extern char *make_md5(char *password); + +int rigctld_password_check(RIG *rig, const char *md5) { int retval = -RIG_EINVAL; //fprintf(fout, "password %s\n", password); - rig_debug(RIG_DEBUG_TRACE, "%s: %s == %s\n", __func__, key1, rigctld_password); + rig_debug(RIG_DEBUG_TRACE, "%s: %s == %s\n", __func__, md5, rigctld_password); is_passwordOK = 0; - if (strcmp((char *)key1, rigctld_password) == 0) + char *mymd5 = make_md5(rigctld_password); + + if (strcmp(md5, mymd5) == 0) { retval = RIG_OK; is_passwordOK = 1; @@ -4955,34 +4962,35 @@ int rigctld_password_check(RIG *rig, const unsigned char *key1, declare_proto_rig(password) { int retval = -RIG_EPROTO; - const char *passwd = arg1; + const char *key = arg1; ENTERFUNC; if (is_rigctld) { - retval = rigctld_password_check(rig, (unsigned char *)passwd, (unsigned char*)"key2"); + retval = rigctld_password_check(rig, key); } else { - retval = rig_password(rig, (unsigned char *) passwd, (unsigned char *)"key2"); + retval = rig_password(rig, key); //retval = RIG_OK; } if (retval == RIG_OK) { rig_debug(RIG_DEBUG_ERR, "%s: #1 password OK\n", __func__); - fprintf(fout, "Logged in\n"); + //fprintf(fout, "Logged in\n"); } else { rig_debug(RIG_DEBUG_ERR, "%s: password error, '%s'!='%s'\n", __func__, - passwd, rigctld_password); + key, rigctld_password); } RETURNFUNC(retval); } +#if 0 // don't think we need this yet /* 0x99 */ declare_proto_rig(set_password) { @@ -4991,6 +4999,7 @@ declare_proto_rig(set_password) rig_debug(RIG_DEBUG_ERR, "%s: set_password %s\n", __func__, rigctld_password); return (RIG_OK); } +#endif /* '0x8d' */ declare_proto_rig(set_twiddle) diff --git a/tests/rigctld.c b/tests/rigctld.c index b625cf161..67ae728fa 100644 --- a/tests/rigctld.c +++ b/tests/rigctld.c @@ -149,7 +149,7 @@ const char *portno = "4532"; const char *src_addr = NULL; /* INADDR_ANY */ const char *multicast_addr = "0.0.0.0"; int multicast_port = 4532; -extern char rigctld_password[64]; +extern char rigctld_password[65]; #define MAXCONFLEN 1024 @@ -238,6 +238,8 @@ static void handle_error(enum rig_debug_level_e lvl, const char *msg) } +extern char *make_md5(char *password); + int main(int argc, char *argv[]) { rig_model_t my_model = RIG_MODEL_DUMMY; @@ -306,6 +308,8 @@ int main(int argc, char *argv[]) case 'A': strncpy(rigctld_password, optarg, sizeof(rigctld_password) - 1); + char *md5 = make_md5(rigctld_password); + printf("Secret key: %s\n", md5); break; case 'm': @@ -1061,20 +1065,24 @@ int main(int argc, char *argv[]) #ifdef HAVE_PTHREAD /* allow threads to finish current action */ mutex_rigctld(1); - + TRACE; if (client_count) { rig_debug(RIG_DEBUG_WARN, "%u outstanding client(s)\n", client_count); } rig_close(my_rig); + TRACE; mutex_rigctld(0); + TRACE; #else rig_close(my_rig); /* close port */ #endif + TRACE; network_multicast_publisher_stop(my_rig); + TRACE; rig_cleanup(my_rig); /* if you care about memory */ #ifdef __MINGW32__