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. */
38 int
lutil_get_filed_password(const char * filename,struct berval * passwd)39 lutil_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