1/*	$NetBSD: passfile.c,v 1.3 2021/08/14 16:14:58 christos Exp $	*/
2
3/* $OpenLDAP$ */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1998-2021 The OpenLDAP Foundation.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
12 *
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
16 */
17
18#include <sys/cdefs.h>
19__RCSID("$NetBSD: passfile.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
20
21#include "portable.h"
22
23#include <stdio.h>
24
25#include <ac/stdlib.h>
26#include <ac/ctype.h>
27#include <ac/string.h>
28
29#ifdef HAVE_FSTAT
30#include <sys/types.h>
31#include <sys/stat.h>
32#endif /* HAVE_FSTAT */
33
34#include <lber.h>
35#include <lutil.h>
36
37/* Get a password from a file. */
38int
39lutil_get_filed_password(
40	const char *filename,
41	struct berval *passwd )
42{
43	size_t nread, nleft, nr;
44	FILE *f = fopen( filename, "r" );
45
46	if( f == NULL ) {
47		perror( filename );
48		return -1;
49	}
50
51	passwd->bv_val = NULL;
52	passwd->bv_len = 4096;
53
54#ifdef HAVE_FSTAT
55	{
56		struct stat sb;
57		if ( fstat( fileno( f ), &sb ) == 0 ) {
58			if( sb.st_mode & 006 ) {
59				fprintf( stderr, _("Warning: Password file %s"
60					" is publicly readable/writeable\n"),
61					filename );
62			}
63
64			if ( sb.st_size )
65				passwd->bv_len = sb.st_size;
66		}
67	}
68#endif /* HAVE_FSTAT */
69
70	passwd->bv_val = (char *) ber_memalloc( passwd->bv_len + 1 );
71	if( passwd->bv_val == NULL ) {
72		perror( filename );
73		fclose( f );
74		return -1;
75	}
76
77	nread = 0;
78	nleft = passwd->bv_len;
79	do {
80		if( nleft == 0 ) {
81			/* double the buffer size */
82			char *p = (char *) ber_memrealloc( passwd->bv_val,
83				2 * passwd->bv_len + 1 );
84			if( p == NULL ) {
85				ber_memfree( passwd->bv_val );
86				passwd->bv_val = NULL;
87				passwd->bv_len = 0;
88				fclose( f );
89				return -1;
90			}
91			nleft = passwd->bv_len;
92			passwd->bv_len *= 2;
93			passwd->bv_val = p;
94		}
95
96		nr = fread( &passwd->bv_val[nread], 1, nleft, f );
97
98		if( nr < nleft && ferror( f ) ) {
99			ber_memfree( passwd->bv_val );
100			passwd->bv_val = NULL;
101			passwd->bv_len = 0;
102			fclose( f );
103			return -1;
104		}
105
106		nread += nr;
107		nleft -= nr;
108	} while ( !feof(f) );
109
110	passwd->bv_len = nread;
111	passwd->bv_val[nread] = '\0';
112
113	fclose( f );
114	return 0;
115}
116