|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2001-2012 Free Software Foundation, Inc.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of GnuTLS.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* GnuTLS is free software: you can redistribute it and/or modify it
|
|
Packit Service |
4684c1 |
* under the terms of the GNU General Public License as published by
|
|
Packit Service |
4684c1 |
* the Free Software Foundation, either version 3 of the License, or
|
|
Packit Service |
4684c1 |
* (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* GnuTLS is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see
|
|
Packit Service |
4684c1 |
* <https://www.gnu.org/licenses/>.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <config.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <stdio.h>
|
|
Packit Service |
4684c1 |
#include <string.h>
|
|
Packit Service |
4684c1 |
#include <stdlib.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/gnutls.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/crypto.h> /* for random */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <sys/types.h>
|
|
Packit Service |
4684c1 |
#include <sys/stat.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#ifndef _WIN32
|
|
Packit Service |
4684c1 |
#include <pwd.h>
|
|
Packit Service |
4684c1 |
#include <unistd.h>
|
|
Packit Service |
4684c1 |
#else
|
|
Packit Service |
4684c1 |
#include <windows.h>
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Gnulib portability files. */
|
|
Packit Service |
4684c1 |
#include <getpass.h>
|
|
Packit Service |
4684c1 |
#include <minmax.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <srptool-args.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* This may need some rewrite. A lot of stuff which should be here
|
|
Packit Service |
4684c1 |
* are in the library, which is not good.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int crypt_int(const char *username, const char *passwd, int salt,
|
|
Packit Service |
4684c1 |
const char *tpasswd_conf, const char *tpasswd, int uindex);
|
|
Packit Service |
4684c1 |
static int read_conf_values(gnutls_datum_t * g, gnutls_datum_t * n,
|
|
Packit Service |
4684c1 |
char *str);
|
|
Packit Service |
4684c1 |
static int _verify_passwd_int(const char *username, const char *passwd,
|
|
Packit Service |
4684c1 |
char *verifier, const char *salt,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * g,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * n);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void print_num(const char *msg, const gnutls_datum_t * num)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned int i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf("%s:\t", msg);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < num->size; i++) {
|
|
Packit Service |
4684c1 |
if (i != 0 && i % 12 == 0)
|
|
Packit Service |
4684c1 |
printf("\n\t");
|
|
Packit Service |
4684c1 |
else if (i != 0 && i != num->size)
|
|
Packit Service |
4684c1 |
printf(":");
|
|
Packit Service |
4684c1 |
printf("%.2x", num->data[i]);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
printf("\n\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int generate_create_conf(const char *tpasswd_conf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
FILE *fp;
|
|
Packit Service |
4684c1 |
char line[5 * 1024];
|
|
Packit Service |
4684c1 |
int index = 1, srp_idx;
|
|
Packit Service |
4684c1 |
gnutls_datum_t g, n;
|
|
Packit Service |
4684c1 |
gnutls_datum_t str_g, str_n;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fp = fopen(tpasswd_conf, "w");
|
|
Packit Service |
4684c1 |
if (fp == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot open file '%s'\n", tpasswd_conf);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (index = 1; index <= 5; index++) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (index == 1) {
|
|
Packit Service |
4684c1 |
srp_idx = 2;
|
|
Packit Service |
4684c1 |
n = gnutls_srp_1536_group_prime;
|
|
Packit Service |
4684c1 |
g = gnutls_srp_1536_group_generator;
|
|
Packit Service |
4684c1 |
} else if (index == 2) {
|
|
Packit Service |
4684c1 |
srp_idx = 3;
|
|
Packit Service |
4684c1 |
n = gnutls_srp_2048_group_prime;
|
|
Packit Service |
4684c1 |
g = gnutls_srp_2048_group_generator;
|
|
Packit Service |
4684c1 |
} else if (index == 3) {
|
|
Packit Service |
4684c1 |
srp_idx = 4;
|
|
Packit Service |
4684c1 |
n = gnutls_srp_3072_group_prime;
|
|
Packit Service |
4684c1 |
g = gnutls_srp_3072_group_generator;
|
|
Packit Service |
4684c1 |
} else if (index == 4) {
|
|
Packit Service |
4684c1 |
srp_idx = 5;
|
|
Packit Service |
4684c1 |
n = gnutls_srp_4096_group_prime;
|
|
Packit Service |
4684c1 |
g = gnutls_srp_4096_group_generator;
|
|
Packit Service |
4684c1 |
} else if (index == 5) {
|
|
Packit Service |
4684c1 |
srp_idx = 7;
|
|
Packit Service |
4684c1 |
n = gnutls_srp_8192_group_prime;
|
|
Packit Service |
4684c1 |
g = gnutls_srp_8192_group_generator;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Unknown index: %d\n", index);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf("\nGroup %d, of %d bits:\n", srp_idx, n.size * 8);
|
|
Packit Service |
4684c1 |
print_num("Generator", &g);
|
|
Packit Service |
4684c1 |
print_num("Prime", &n);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (gnutls_srp_base64_encode_alloc(&n, &str_n) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Could not encode\n");
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (gnutls_srp_base64_encode_alloc(&g, &str_g) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Could not encode\n");
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
sprintf(line, "%d:%s:%s\n", srp_idx, str_n.data, str_g.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_free(str_n.data);
|
|
Packit Service |
4684c1 |
gnutls_free(str_g.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fwrite(line, 1, strlen(line), fp);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* The format of a tpasswd file is:
|
|
Packit Service |
4684c1 |
* username:verifier:salt:index
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* index is the index of the prime-generator pair in tpasswd.conf
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_verify_passwd_int(const char *username, const char *passwd,
|
|
Packit Service |
4684c1 |
char *verifier, const char *salt,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * g, const gnutls_datum_t * n)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
char _salt[1024];
|
|
Packit Service |
4684c1 |
gnutls_datum_t tmp, raw_salt, new_verifier;
|
|
Packit Service |
4684c1 |
size_t salt_size;
|
|
Packit Service |
4684c1 |
char *pos;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (salt == NULL || verifier == NULL)
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (strlen(salt) >= sizeof(_salt)) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Too long salt.\n");
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* copy salt, and null terminate after the ':' */
|
|
Packit Service |
4684c1 |
strcpy(_salt, salt);
|
|
Packit Service |
4684c1 |
pos = strchr(_salt, ':');
|
|
Packit Service |
4684c1 |
if (pos != NULL)
|
|
Packit Service |
4684c1 |
*pos = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* convert salt to binary. */
|
|
Packit Service |
4684c1 |
tmp.data = (void *) _salt;
|
|
Packit Service |
4684c1 |
tmp.size = strlen(_salt);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (gnutls_srp_base64_decode_alloc(&tmp, &raw_salt) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Could not decode salt.\n");
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (gnutls_srp_verifier
|
|
Packit Service |
4684c1 |
(username, passwd, &raw_salt, g, n, &new_verifier) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Could not make the verifier\n");
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
free(raw_salt.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* encode the verifier into _salt */
|
|
Packit Service |
4684c1 |
salt_size = sizeof(_salt);
|
|
Packit Service |
4684c1 |
memset(_salt, 0, salt_size);
|
|
Packit Service |
4684c1 |
if (gnutls_srp_base64_encode(&new_verifier, _salt, &salt_size) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Encoding error\n");
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
free(new_verifier.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (strncmp(verifier, _salt, strlen(_salt)) == 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Password verified\n");
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Password does NOT match\n");
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int filecopy(const char *src, const char *dst)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
FILE *fp, *fp2;
|
|
Packit Service |
4684c1 |
char line[5 * 1024];
|
|
Packit Service |
4684c1 |
char *p;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fp = fopen(dst, "w");
|
|
Packit Service |
4684c1 |
if (fp == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot open '%s' for write\n", dst);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fp2 = fopen(src, "r");
|
|
Packit Service |
4684c1 |
if (fp2 == NULL) {
|
|
Packit Service |
4684c1 |
/* empty file */
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
line[sizeof(line) - 1] = 0;
|
|
Packit Service |
4684c1 |
do {
|
|
Packit Service |
4684c1 |
p = fgets(line, sizeof(line) - 1, fp2);
|
|
Packit Service |
4684c1 |
if (p == NULL)
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fputs(line, fp);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
while (1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
fclose(fp2);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* accepts password file */
|
|
Packit Service |
4684c1 |
static int find_strchr(const char *username, const char *file)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
FILE *fp;
|
|
Packit Service |
4684c1 |
char *pos;
|
|
Packit Service |
4684c1 |
char line[5 * 1024];
|
|
Packit Service |
4684c1 |
unsigned int i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fp = fopen(file, "r");
|
|
Packit Service |
4684c1 |
if (fp == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot open file '%s'\n", file);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
while (fgets(line, sizeof(line), fp) != NULL) {
|
|
Packit Service |
4684c1 |
/* move to first ':' */
|
|
Packit Service |
4684c1 |
i = 0;
|
|
Packit Service |
4684c1 |
while ((line[i] != ':') && (line[i] != '\0')
|
|
Packit Service |
4684c1 |
&& (i < sizeof(line))) {
|
|
Packit Service |
4684c1 |
i++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (strncmp(username, line, MAX(i, strlen(username))) == 0) {
|
|
Packit Service |
4684c1 |
/* find the index */
|
|
Packit Service |
4684c1 |
pos = strrchr(line, ':');
|
|
Packit Service |
4684c1 |
pos++;
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
return atoi(pos);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Parses the tpasswd files, in order to verify the given
|
|
Packit Service |
4684c1 |
* username/password pair.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
verify_passwd(const char *conffile, const char *tpasswd,
|
|
Packit Service |
4684c1 |
const char *username, const char *passwd)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
FILE *fp;
|
|
Packit Service |
4684c1 |
char line[5 * 1024];
|
|
Packit Service |
4684c1 |
unsigned int i;
|
|
Packit Service |
4684c1 |
gnutls_datum_t g, n;
|
|
Packit Service |
4684c1 |
int iindex;
|
|
Packit Service |
4684c1 |
char *p, *pos;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
iindex = find_strchr(username, tpasswd);
|
|
Packit Service |
4684c1 |
if (iindex == -1) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot find '%s' in %s\n", username,
|
|
Packit Service |
4684c1 |
tpasswd);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fp = fopen(conffile, "r");
|
|
Packit Service |
4684c1 |
if (fp == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot find %s\n", conffile);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
do {
|
|
Packit Service |
4684c1 |
p = fgets(line, sizeof(line) - 1, fp);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
while (p != NULL && atoi(p) != iindex);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (p == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot find entry in %s\n", conffile);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
line[sizeof(line) - 1] = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((iindex = read_conf_values(&g, &n, line)) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot parse conf file '%s'\n", conffile);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fp = fopen(tpasswd, "r");
|
|
Packit Service |
4684c1 |
if (fp == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot open file '%s'\n", tpasswd);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
while (fgets(line, sizeof(line), fp) != NULL) {
|
|
Packit Service |
4684c1 |
/* move to first ':'
|
|
Packit Service |
4684c1 |
* This is the actual verifier.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
i = 0;
|
|
Packit Service |
4684c1 |
while ((line[i] != ':') && (line[i] != '\0')
|
|
Packit Service |
4684c1 |
&& (i < sizeof(line))) {
|
|
Packit Service |
4684c1 |
i++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (strncmp(username, line, MAX(i, strlen(username))) == 0) {
|
|
Packit Service |
4684c1 |
char *verifier_pos, *salt_pos;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pos = strchr(line, ':');
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
if (pos == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr,
|
|
Packit Service |
4684c1 |
"Cannot parse conf file '%s'\n",
|
|
Packit Service |
4684c1 |
conffile);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
pos++;
|
|
Packit Service |
4684c1 |
verifier_pos = pos;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Move to the salt */
|
|
Packit Service |
4684c1 |
pos = strchr(pos, ':');
|
|
Packit Service |
4684c1 |
if (pos == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr,
|
|
Packit Service |
4684c1 |
"Cannot parse conf file '%s'\n",
|
|
Packit Service |
4684c1 |
conffile);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
pos++;
|
|
Packit Service |
4684c1 |
salt_pos = pos;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return _verify_passwd_int(username, passwd,
|
|
Packit Service |
4684c1 |
verifier_pos, salt_pos,
|
|
Packit Service |
4684c1 |
&g, &n);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define KPASSWD "/etc/tpasswd"
|
|
Packit Service |
4684c1 |
#define KPASSWD_CONF "/etc/tpasswd.conf"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void tls_log_func(int level, const char *str)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf(stderr, "|<%d>| %s", level, str);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int main(int argc, char **argv)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const char *passwd;
|
|
Packit Service |
4684c1 |
int salt_size, ret;
|
|
Packit Service |
4684c1 |
const char *fpasswd, *fpasswd_conf;
|
|
Packit Service |
4684c1 |
const char *username;
|
|
Packit Service |
4684c1 |
#ifndef _WIN32
|
|
Packit Service |
4684c1 |
struct passwd *pwd;
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((ret = gnutls_global_init()) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret));
|
|
Packit Service |
4684c1 |
exit(1);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
umask(066);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
optionProcess(&srptoolOptions, argc, argv);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_global_set_log_function(tls_log_func);
|
|
Packit Service |
4684c1 |
gnutls_global_set_log_level(OPT_VALUE_DEBUG);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (HAVE_OPT(CREATE_CONF)) {
|
|
Packit Service |
4684c1 |
return generate_create_conf(OPT_ARG(CREATE_CONF));
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (HAVE_OPT(PASSWD))
|
|
Packit Service |
4684c1 |
fpasswd = OPT_ARG(PASSWD);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
fpasswd = (char *) KPASSWD;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (HAVE_OPT(PASSWD_CONF))
|
|
Packit Service |
4684c1 |
fpasswd_conf = OPT_ARG(PASSWD_CONF);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
fpasswd_conf = (char *) KPASSWD_CONF;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (HAVE_OPT(USERNAME))
|
|
Packit Service |
4684c1 |
username = OPT_ARG(USERNAME);
|
|
Packit Service |
4684c1 |
else {
|
|
Packit Service |
4684c1 |
#ifndef _WIN32
|
|
Packit Service |
4684c1 |
pwd = getpwuid(getuid());
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pwd == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "No such user\n");
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
username = pwd->pw_name;
|
|
Packit Service |
4684c1 |
#else
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Please specify a user\n");
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
salt_size = 16;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
passwd = getpass("Enter password: ");
|
|
Packit Service |
4684c1 |
if (passwd == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Please specify a password\n");
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* not ready yet */
|
|
Packit Service |
4684c1 |
if (HAVE_OPT(VERIFY)) {
|
|
Packit Service |
4684c1 |
return verify_passwd(fpasswd_conf, fpasswd,
|
|
Packit Service |
4684c1 |
username, passwd);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return crypt_int(username, passwd, salt_size,
|
|
Packit Service |
4684c1 |
fpasswd_conf, fpasswd, OPT_VALUE_INDEX);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static char *_srp_crypt(const char *username, const char *passwd,
|
|
Packit Service |
4684c1 |
int salt_size, const gnutls_datum_t * g,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * n)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned char salt[128];
|
|
Packit Service |
4684c1 |
static char result[1024];
|
|
Packit Service |
4684c1 |
gnutls_datum_t dat_salt, txt_salt;
|
|
Packit Service |
4684c1 |
gnutls_datum_t verifier, txt_verifier;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((unsigned) salt_size > sizeof(salt))
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* generate the salt
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (gnutls_rnd(GNUTLS_RND_NONCE, salt, salt_size) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Could not create nonce\n");
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
dat_salt.data = salt;
|
|
Packit Service |
4684c1 |
dat_salt.size = salt_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (gnutls_srp_verifier
|
|
Packit Service |
4684c1 |
(username, passwd, &dat_salt, g, n, &verifier) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Error getting verifier\n");
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* base64 encode the verifier */
|
|
Packit Service |
4684c1 |
if (gnutls_srp_base64_encode_alloc(&verifier, &txt_verifier) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Error encoding\n");
|
|
Packit Service |
4684c1 |
free(verifier.data);
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
free(verifier.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (gnutls_srp_base64_encode_alloc(&dat_salt, &txt_salt) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Error encoding\n");
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
sprintf(result, "%s:%s", txt_verifier.data, txt_salt.data);
|
|
Packit Service |
4684c1 |
free(txt_salt.data);
|
|
Packit Service |
4684c1 |
free(txt_verifier.data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
crypt_int(const char *username, const char *passwd, int salt_size,
|
|
Packit Service |
4684c1 |
const char *tpasswd_conf, const char *tpasswd, int uindex)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
FILE *fp;
|
|
Packit Service |
4684c1 |
char *cr;
|
|
Packit Service |
4684c1 |
gnutls_datum_t g, n;
|
|
Packit Service |
4684c1 |
char line[5 * 1024];
|
|
Packit Service |
4684c1 |
char *p, *pp;
|
|
Packit Service |
4684c1 |
int iindex;
|
|
Packit Service |
4684c1 |
char tmpname[1024];
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fp = fopen(tpasswd_conf, "r");
|
|
Packit Service |
4684c1 |
if (fp == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot find %s\n", tpasswd_conf);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
do { /* find the specified uindex in file */
|
|
Packit Service |
4684c1 |
p = fgets(line, sizeof(line) - 1, fp);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
while (p != NULL && (iindex = atoi(p)) != uindex);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (p == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot find entry in %s\n", tpasswd_conf);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
line[sizeof(line) - 1] = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
if ((iindex = read_conf_values(&g, &n, line)) < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot parse conf file '%s'\n",
|
|
Packit Service |
4684c1 |
tpasswd_conf);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cr = _srp_crypt(username, passwd, salt_size, &g, &n);
|
|
Packit Service |
4684c1 |
if (cr == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot _srp_crypt()...\n");
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
/* delete previous entry */
|
|
Packit Service |
4684c1 |
struct stat st;
|
|
Packit Service |
4684c1 |
FILE *fp2;
|
|
Packit Service |
4684c1 |
int put;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (strlen(tpasswd) + 5 > sizeof(tmpname)) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "file '%s' is tooooo long\n",
|
|
Packit Service |
4684c1 |
tpasswd);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
snprintf(tmpname, sizeof(tmpname), "%s.tmp", tpasswd);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (stat(tmpname, &st) != -1) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "file '%s' is locked\n", tpasswd);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (filecopy(tpasswd, tmpname) != 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot copy '%s' to '%s'\n",
|
|
Packit Service |
4684c1 |
tpasswd, tmpname);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fp = fopen(tpasswd, "w");
|
|
Packit Service |
4684c1 |
if (fp == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot open '%s' for write\n",
|
|
Packit Service |
4684c1 |
tpasswd);
|
|
Packit Service |
4684c1 |
(void)remove(tmpname);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fp2 = fopen(tmpname, "r");
|
|
Packit Service |
4684c1 |
if (fp2 == NULL) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Cannot open '%s' for read\n",
|
|
Packit Service |
4684c1 |
tmpname);
|
|
Packit Service |
4684c1 |
(void)remove(tmpname);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
put = 0;
|
|
Packit Service |
4684c1 |
do {
|
|
Packit Service |
4684c1 |
p = fgets(line, sizeof(line) - 1, fp2);
|
|
Packit Service |
4684c1 |
if (p == NULL)
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pp = strchr(line, ':');
|
|
Packit Service |
4684c1 |
if (pp == NULL)
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (strncmp(p, username,
|
|
Packit Service |
4684c1 |
MAX(strlen(username),
|
|
Packit Service |
4684c1 |
(unsigned int) (pp - p))) == 0) {
|
|
Packit Service |
4684c1 |
put = 1;
|
|
Packit Service |
4684c1 |
fprintf(fp, "%s:%s:%u\n", username, cr,
|
|
Packit Service |
4684c1 |
iindex);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
fputs(line, fp);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
while (1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (put == 0) {
|
|
Packit Service |
4684c1 |
fprintf(fp, "%s:%s:%u\n", username, cr, iindex);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fclose(fp);
|
|
Packit Service |
4684c1 |
fclose(fp2);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
(void)remove(tmpname);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* this function parses tpasswd.conf file. Format is:
|
|
Packit Service |
4684c1 |
* int(index):base64(n):base64(g)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
read_conf_values(gnutls_datum_t * g, gnutls_datum_t * n, char *str)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
char *p;
|
|
Packit Service |
4684c1 |
int len;
|
|
Packit Service |
4684c1 |
int index, ret;
|
|
Packit Service |
4684c1 |
gnutls_datum_t dat;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
index = atoi(str);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p = strrchr(str, ':'); /* we have g */
|
|
Packit Service |
4684c1 |
if (p == NULL) {
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*p = '\0';
|
|
Packit Service |
4684c1 |
p++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* read the generator */
|
|
Packit Service |
4684c1 |
len = strlen(p);
|
|
Packit Service |
4684c1 |
if (p[len - 1] == '\n')
|
|
Packit Service |
4684c1 |
len--;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
dat.data = (void *) p;
|
|
Packit Service |
4684c1 |
dat.size = len;
|
|
Packit Service |
4684c1 |
ret = gnutls_srp_base64_decode_alloc(&dat, g);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Decoding error\n");
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* now go for n - modulo */
|
|
Packit Service |
4684c1 |
p = strrchr(str, ':'); /* we have n */
|
|
Packit Service |
4684c1 |
if (p == NULL) {
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*p = '\0';
|
|
Packit Service |
4684c1 |
p++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
dat.data = (void *) p;
|
|
Packit Service |
4684c1 |
dat.size = strlen(p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_srp_base64_decode_alloc(&dat, n);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Decoding error\n");
|
|
Packit Service |
4684c1 |
free(g->data);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return index;
|
|
Packit Service |
4684c1 |
}
|