Move password functions to own file.

This commit is contained in:
Roger A. Light 2020-10-12 13:45:37 +01:00
parent be8b94189c
commit f85e004415
11 changed files with 320 additions and 149 deletions

3
.gitignore vendored
View File

@ -15,6 +15,8 @@ vglog*
c/*.test
cpp/*.test
apps/mosquitto_passwd/mosquitto_passwd
build/
client/mosquitto_pub
@ -51,7 +53,6 @@ out/
src/db_dump/mosquitto_db_dump
src/mosquitto
src/mosquitto_passwd
test/broker/broker.pid
test/test_client

View File

@ -1,9 +1,10 @@
include config.mk
DIRS=lib client src
DIRS=lib apps client src
DOCDIRS=man
DISTDIRS=man
DISTFILES= \
apps/ \
client/ \
examples/ \
installer/ \

27
apps/Makefile Normal file
View File

@ -0,0 +1,27 @@
DIRS= \
mosquitto_passwd
.PHONY : all binary check clean reallyclean test install uninstall
all :
set -e; for d in ${DIRS}; do $(MAKE) -C $${d}; done
binary :
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} $@; done
clean :
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} $@; done
reallyclean :
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} $@; done
check : test
test : mosquitto
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} $@; done
install :
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} $@; done
uninstall :
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} $@; done

View File

@ -0,0 +1,36 @@
include ../../config.mk
.PHONY: all install uninstall clean reallyclean
OBJS= mosquitto_passwd.o \
memory_mosq.o \
misc_mosq.o \
password_mosq.o
mosquitto_passwd : ${OBJS}
${CROSS_COMPILE}${CC} ${APP_LDFLAGS} $^ -o $@ $(PASSWD_LDADD)
mosquitto_passwd.o : mosquitto_passwd.c
${CROSS_COMPILE}${CC} $(APP_CPPFLAGS) $(APP_CFLAGS) -c $< -o $@
memory_mosq.o : ../../lib/memory_mosq.c
${CROSS_COMPILE}${CC} $(APP_CPPFLAGS) $(APP_CFLAGS) -c $< -o $@
misc_mosq.o : ../../lib/misc_mosq.c ../../lib/misc_mosq.h
${CROSS_COMPILE}${CC} $(APP_CPPFLAGS) $(APP_CFLAGS) -c $< -o $@
password_mosq.o : ../../src/password_mosq.c ../../src/password_mosq.h
${CROSS_COMPILE}${CC} $(APP_CPPFLAGS) $(APP_CFLAGS) -c $< -o $@
install : all
$(INSTALL) -d "${DESTDIR}$(prefix)/bin"
$(INSTALL) ${STRIP_OPTS} mosquitto_passwd "${DESTDIR}${prefix}/bin/mosquitto_passwd"
uninstall :
-rm -f "${DESTDIR}${prefix}/bin/mosquitto_passwd"
clean :
-rm -f *.o mosquitto_passwd *.gcda *.gcno
reallyclean : clean
-rm -rf *.orig *.db

View File

@ -17,15 +17,14 @@ Contributors:
#include "config.h"
#include <errno.h>
#include <openssl/opensslv.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/buffer.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "password_mosq.h"
#ifdef WIN32
# include <windows.h>
@ -54,11 +53,6 @@ Contributors:
#include "misc_mosq.h"
enum pwhash{
pw_sha512 = 6,
pw_sha512_pbkdf2 = 7,
};
struct cb_helper {
const char *line;
const char *username;
@ -66,7 +60,7 @@ struct cb_helper {
bool found;
};
static enum pwhash hashtype = pw_sha512_pbkdf2;
static enum mosquitto_pwhash_type hashtype = pw_sha512_pbkdf2;
#ifdef WIN32
static FILE *mpw_tmpfile(void)
@ -108,34 +102,6 @@ static FILE *mpw_tmpfile(void)
#endif
int base64_encode(unsigned char *in, unsigned int in_len, char **encoded)
{
BIO *bmem, *b64;
BUF_MEM *bptr;
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, in, in_len);
if(BIO_flush(b64) != 1){
BIO_free_all(b64);
return 1;
}
BIO_get_mem_ptr(b64, &bptr);
*encoded = malloc(bptr->length+1);
if(!(*encoded)){
BIO_free_all(b64);
return 1;
}
memcpy(*encoded, bptr->data, bptr->length);
(*encoded)[bptr->length] = '\0';
BIO_free_all(b64);
return 0;
}
void print_usage(void)
{
printf("mosquitto_passwd is a tool for managing password files for mosquitto.\n\n");
@ -154,62 +120,26 @@ void print_usage(void)
int output_new_password(FILE *fptr, const char *username, const char *password)
{
int rc;
unsigned char salt[SALT_LEN];
char *salt64 = NULL, *hash64 = NULL;
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int hash_len;
const EVP_MD *digest;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_MD_CTX context;
#else
EVP_MD_CTX *context;
#endif
struct mosquitto_pw pw;
rc = RAND_bytes(salt, SALT_LEN);
if(!rc){
fprintf(stderr, "Error: Insufficient entropy available to perform password generation.\n");
memset(&pw, 0, sizeof(pw));
pw.hashtype = hashtype;
if(pw__hash(password, &pw, true)){
fprintf(stderr, "Error: Unable to hash password.\n");
return 1;
}
rc = base64_encode(salt, SALT_LEN, &salt64);
rc = base64_encode(pw.salt, sizeof(pw.salt), &salt64);
if(rc){
free(salt64);
fprintf(stderr, "Error: Unable to encode salt.\n");
return 1;
}
digest = EVP_get_digestbyname("sha512");
if(!digest){
free(salt64);
fprintf(stderr, "Error: Unable to create openssl digest.\n");
return 1;
}
if(hashtype == pw_sha512){
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_MD_CTX_init(&context);
EVP_DigestInit_ex(&context, digest, NULL);
EVP_DigestUpdate(&context, password, strlen(password));
EVP_DigestUpdate(&context, salt, SALT_LEN);
EVP_DigestFinal_ex(&context, hash, &hash_len);
EVP_MD_CTX_cleanup(&context);
#else
context = EVP_MD_CTX_new();
EVP_DigestInit_ex(context, digest, NULL);
EVP_DigestUpdate(context, password, strlen(password));
EVP_DigestUpdate(context, salt, SALT_LEN);
EVP_DigestFinal_ex(context, hash, &hash_len);
EVP_MD_CTX_free(context);
#endif
}else{
hash_len = sizeof(hash);
PKCS5_PBKDF2_HMAC(password, strlen(password),
salt, SALT_LEN, 20000,
digest, hash_len, hash);
}
rc = base64_encode(hash, hash_len, &hash64);
rc = base64_encode(pw.password_hash, sizeof(pw.password_hash), &hash64);
if(rc){
free(salt64);
free(hash64);

View File

@ -144,6 +144,8 @@ endif
STATIC_LIB_DEPS:=
APP_CPPFLAGS=$(CPPFLAGS) -I. -I../../ -I../../include -I../../src -I../../lib
LIB_CPPFLAGS=$(CPPFLAGS) -I. -I.. -I../include -I../../include
ifeq ($(WITH_BUNDLED_DEPS),yes)
LIB_CPPFLAGS:=$(LIB_CPPFLAGS) -I../src/deps

View File

@ -2,11 +2,7 @@ include ../config.mk
.PHONY: all install uninstall clean reallyclean
ifeq ($(WITH_TLS),yes)
all : mosquitto mosquitto_passwd
else
all : mosquitto
endif
OBJS= mosquitto.o \
alias_mosq.o \
@ -44,6 +40,7 @@ OBJS= mosquitto.o \
net_mosq_ocsp.o \
packet_datatypes.o \
packet_mosq.o \
password_mosq.o \
property_broker.o \
property_mosq.o \
persist_read.o \
@ -187,6 +184,9 @@ net_mosq_ocsp.o : ../lib/net_mosq_ocsp.c ../lib/net_mosq.h
net_mosq.o : ../lib/net_mosq.c ../lib/net_mosq.h
${CROSS_COMPILE}${CC} $(BROKER_CPPFLAGS) $(BROKER_CFLAGS) -c $< -o $@
password_mosq.o : password_mosq.c password_mosq.h mosquitto_broker_internal.h
${CROSS_COMPILE}${CC} $(BROKER_CPPFLAGS) $(BROKER_CFLAGS) -c $< -o $@
persist_read.o : persist_read.c persist.h mosquitto_broker_internal.h
${CROSS_COMPILE}${CC} $(BROKER_CPPFLAGS) $(BROKER_CFLAGS) -c $< -o $@
@ -304,12 +304,6 @@ will_delay.o : will_delay.c mosquitto_broker_internal.h
will_mosq.o : ../lib/will_mosq.c ../lib/will_mosq.h
${CROSS_COMPILE}${CC} $(BROKER_CPPFLAGS) $(BROKER_CFLAGS) -c $< -o $@
mosquitto_passwd : mosquitto_passwd.o misc_mosq.o
${CROSS_COMPILE}${CC} ${LDFLAGS} $^ -o $@ $(PASSWD_LDADD)
mosquitto_passwd.o : mosquitto_passwd.c
${CROSS_COMPILE}${CC} -I.. -I../lib $(CPPFLAGS) $(CFLAGS) -c $< -o $@
plugin_defer.so : plugin_defer.c ../include/mosquitto_plugin.h ../include/mosquitto_broker.h mosquitto_broker_internal.h
${CROSS_COMPILE}${CC} -I. -I../lib -fPIC -shared $< -o $@
@ -322,19 +316,14 @@ install : all
$(INSTALL) -d "${DESTDIR}$(prefix)/include"
$(INSTALL) ../include/mosquitto_broker.h "${DESTDIR}${prefix}/include/mosquitto_broker.h"
$(INSTALL) ../include/mosquitto_plugin.h "${DESTDIR}${prefix}/include/mosquitto_plugin.h"
ifeq ($(WITH_TLS),yes)
$(INSTALL) -d "${DESTDIR}$(prefix)/bin"
$(INSTALL) ${STRIP_OPTS} mosquitto_passwd "${DESTDIR}${prefix}/bin/mosquitto_passwd"
endif
uninstall :
-rm -f "${DESTDIR}${prefix}/sbin/mosquitto"
-rm -f "${DESTDIR}${prefix}/include/mosquitto_broker.h"
-rm -f "${DESTDIR}${prefix}/include/mosquitto_plugin.h"
-rm -f "${DESTDIR}${prefix}/bin/mosquitto_passwd"
clean :
-rm -f *.o mosquitto mosquitto_passwd *.gcda *.gcno
-rm -f *.o mosquitto *.gcda *.gcno
reallyclean : clean
-rm -rf *.orig *.db

View File

@ -48,6 +48,7 @@ Contributors:
#include "mosquitto_broker.h"
#include "mosquitto_plugin.h"
#include "mosquitto.h"
#include "password_mosq.h"
#include "tls_mosq.h"
#include "uthash.h"
@ -170,11 +171,6 @@ enum mosquitto_msg_origin{
mosq_mo_broker = 1
};
enum mosquitto_pwhash_type{
pw_sha512 = 6,
pw_sha512_pbkdf2 = 7
};
struct mosquitto__auth_plugin{
void *lib;
void *user_data;

195
src/password_mosq.c Normal file
View File

@ -0,0 +1,195 @@
/*
Copyright (c) 2012-2020 Roger Light <roger@atchoo.org>
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Roger Light - initial implementation and documentation.
*/
#include "config.h"
#include <errno.h>
#include <openssl/opensslv.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/buffer.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mosquitto.h"
#include "memory_mosq.h"
#include "password_mosq.h"
#ifdef WIN32
# include <windows.h>
# include <process.h>
# ifndef __cplusplus
# if defined(_MSC_VER) && _MSC_VER < 1900
# define bool char
# define true 1
# define false 0
# else
# include <stdbool.h>
# endif
# endif
# define snprintf sprintf_s
# include <io.h>
# include <windows.h>
#else
# include <stdbool.h>
# include <unistd.h>
# include <termios.h>
# include <sys/stat.h>
#endif
#define MAX_BUFFER_LEN 65536
#define SALT_LEN 12
#include "misc_mosq.h"
int base64_encode(unsigned char *in, unsigned int in_len, char **encoded)
{
BIO *bmem, *b64;
BUF_MEM *bptr;
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, in, in_len);
if(BIO_flush(b64) != 1){
BIO_free_all(b64);
return 1;
}
BIO_get_mem_ptr(b64, &bptr);
*encoded = malloc(bptr->length+1);
if(!(*encoded)){
BIO_free_all(b64);
return 1;
}
memcpy(*encoded, bptr->data, bptr->length);
(*encoded)[bptr->length] = '\0';
BIO_free_all(b64);
return 0;
}
int base64__decode(char *in, unsigned char **decoded, unsigned int *decoded_len)
{
BIO *bmem, *b64;
int slen;
slen = strlen(in);
b64 = BIO_new(BIO_f_base64());
if(!b64){
return 1;
}
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new(BIO_s_mem());
if(!bmem){
BIO_free_all(b64);
return 1;
}
b64 = BIO_push(b64, bmem);
BIO_write(bmem, in, slen);
if(BIO_flush(bmem) != 1){
BIO_free_all(b64);
return 1;
}
*decoded = mosquitto__calloc(slen, 1);
if(!(*decoded)){
BIO_free_all(b64);
return 1;
}
*decoded_len = BIO_read(b64, *decoded, slen);
BIO_free_all(b64);
if(*decoded_len <= 0){
mosquitto__free(*decoded);
*decoded = NULL;
*decoded_len = 0;
return 1;
}
return 0;
}
int pw__hash(const char *password, struct mosquitto_pw *pw, bool new_salt)
{
int rc;
unsigned int hash_len;
const EVP_MD *digest;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_MD_CTX context;
#else
EVP_MD_CTX *context;
#endif
if(new_salt){
rc = RAND_bytes(pw->salt, sizeof(pw->salt));
if(!rc){
return MOSQ_ERR_UNKNOWN;
}
}
digest = EVP_get_digestbyname("sha512");
if(!digest){
return MOSQ_ERR_UNKNOWN;
}
if(pw->hashtype == pw_sha512){
#if OPENSSL_VERSION_NUMBER < 0x10100000L
EVP_MD_CTX_init(&context);
EVP_DigestInit_ex(&context, digest, NULL);
EVP_DigestUpdate(&context, password, strlen(password));
EVP_DigestUpdate(&context, pw->salt, sizeof(pw->salt));
EVP_DigestFinal_ex(&context, pw->password_hash, &hash_len);
EVP_MD_CTX_cleanup(&context);
#else
context = EVP_MD_CTX_new();
EVP_DigestInit_ex(context, digest, NULL);
EVP_DigestUpdate(context, password, strlen(password));
EVP_DigestUpdate(context, pw->salt, sizeof(pw->salt));
EVP_DigestFinal_ex(context, pw->password_hash, &hash_len);
EVP_MD_CTX_free(context);
#endif
}else{
hash_len = sizeof(pw->password_hash);
PKCS5_PBKDF2_HMAC(password, strlen(password),
pw->salt, sizeof(pw->salt), 20000,
digest, hash_len, pw->password_hash);
}
return MOSQ_ERR_SUCCESS;
}
int pw__memcmp_const(const void *a, const void *b, size_t len)
{
size_t i;
int rc = 0;
if(!a || !b) return 1;
for(i=0; i<len; i++){
if( ((char *)a)[i] != ((char *)b)[i] ){
rc = 1;
}
}
return rc;
}

39
src/password_mosq.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef PASSWORD_COMMON_H
#define PASSWORD_COMMON_H
/*
Copyright (c) 2012-2020 Roger Light <roger@atchoo.org>
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Roger Light - initial implementation and documentation.
*/
#include <stdbool.h>
enum mosquitto_pwhash_type{
pw_sha512 = 6,
pw_sha512_pbkdf2 = 7,
};
#define SALT_LEN 12
struct mosquitto_pw{
unsigned char password_hash[64]; /* For SHA512 */
unsigned char salt[SALT_LEN];
enum mosquitto_pwhash_type hashtype;
};
int pw__hash(const char *password, struct mosquitto_pw *pw, bool new_salt);
int pw__memcmp_const(const void *ptr1, const void *b, size_t len);
int base64_encode(unsigned char *in, unsigned int in_len, char **encoded);
int base64__decode(char *in, unsigned char **decoded, unsigned int *decoded_len);
#endif

View File

@ -34,8 +34,6 @@ static int unpwd__cleanup(struct mosquitto__unpwd **unpwd, bool reload);
static int psk__file_parse(struct mosquitto_db *db, struct mosquitto__unpwd **psk_id, const char *psk_file);
#ifdef WITH_TLS
static int pw__digest(const char *password, const unsigned char *salt, unsigned int salt_len, unsigned char *hash, unsigned int *hash_len, enum mosquitto_pwhash_type hashtype);
static int base64__decode(char *in, unsigned char **decoded, unsigned int *decoded_len);
static int mosquitto__memcmp_const(const void *ptr1, const void *b, size_t len);
#endif
@ -1309,47 +1307,4 @@ int pw__digest(const char *password, const unsigned char *salt, unsigned int sal
return MOSQ_ERR_SUCCESS;
}
int base64__decode(char *in, unsigned char **decoded, unsigned int *decoded_len)
{
BIO *bmem, *b64;
int slen;
slen = strlen(in);
b64 = BIO_new(BIO_f_base64());
if(!b64){
return 1;
}
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new(BIO_s_mem());
if(!bmem){
BIO_free_all(b64);
return 1;
}
b64 = BIO_push(b64, bmem);
BIO_write(bmem, in, slen);
if(BIO_flush(bmem) != 1){
BIO_free_all(b64);
return 1;
}
*decoded = mosquitto__calloc(slen, 1);
if(!(*decoded)){
BIO_free_all(b64);
return 1;
}
*decoded_len = BIO_read(b64, *decoded, slen);
BIO_free_all(b64);
if(*decoded_len <= 0){
mosquitto__free(*decoded);
*decoded = NULL;
*decoded_len = 0;
return 1;
}
return 0;
}
#endif