verify_file_perms_ownership() to just return if the file doesn't exist
[fwknop.git] / server / utils.c
1 /*
2  *****************************************************************************
3  *
4  * File:    utils.c
5  *
6  * Author:  Damien S. Stuart
7  *
8  * Purpose: General/Generic functions for the fwknop server.
9  *
10  * Copyright 2010 Damien Stuart (dstuart@dstuart.org)
11  *
12  *  License (GNU Public License):
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
27  *  USA
28  *
29  *****************************************************************************
30 */
31 #include "fwknopd_common.h"
32 #include "utils.h"
33
34 /* Generic hex dump function.
35 */
36 void
37 hex_dump(const unsigned char *data, const int size)
38 {
39     int ln, i, j = 0;
40     char ascii_str[17] = {0};
41
42     for(i=0; i<size; i++)
43     {
44         if((i % 16) == 0)
45         {
46             printf(" %s\n  0x%.4x:  ", ascii_str, i);
47             memset(ascii_str, 0x0, 17);
48             j = 0;
49         }
50
51         printf("%.2x ", data[i]);
52
53         ascii_str[j++] = (data[i] < 0x20 || data[i] > 0x7e) ? '.' : data[i];
54
55         if(j == 8)
56             printf(" ");
57     }
58
59     /* Remainder...
60     */
61     ln = strlen(ascii_str);
62     if(ln > 0)
63     {
64         for(i=0; i < 16-ln; i++)
65             printf("   ");
66
67         printf(" %s\n\n", ascii_str);
68     }
69 }
70
71 /* Show the fields of the FKO context.
72 */
73 char *
74 dump_ctx(fko_ctx_t ctx)
75 {
76     static char buf[CTX_DUMP_BUFSIZE];
77     char       *ndx;
78     int         cp;
79
80     char       *rand_val        = NULL;
81     char       *username        = NULL;
82     char       *version         = NULL;
83     char       *spa_message     = NULL;
84     char       *nat_access      = NULL;
85     char       *server_auth     = NULL;
86     char       *enc_data        = NULL;
87     char       *spa_digest      = NULL;
88     char       *spa_data        = NULL;
89
90     time_t      timestamp       = 0;
91     short       msg_type        = -1;
92     short       digest_type     = -1;
93     int         client_timeout  = -1;
94
95     /* Should be checking return values, but this is temp code. --DSS
96     */
97     fko_get_rand_value(ctx, &rand_val);
98     fko_get_username(ctx, &username);
99     fko_get_timestamp(ctx, &timestamp);
100     fko_get_version(ctx, &version);
101     fko_get_spa_message_type(ctx, &msg_type);
102     fko_get_spa_message(ctx, &spa_message);
103     fko_get_spa_nat_access(ctx, &nat_access);
104     fko_get_spa_server_auth(ctx, &server_auth);
105     fko_get_spa_client_timeout(ctx, &client_timeout);
106     fko_get_spa_digest_type(ctx, &digest_type);
107     fko_get_encoded_data(ctx, &enc_data);
108     fko_get_spa_digest(ctx, &spa_digest);
109     fko_get_spa_data(ctx, &spa_data);
110
111     memset(buf, 0x0, CTX_DUMP_BUFSIZE);
112
113     ndx = buf;
114
115     cp = sprintf(ndx, "SPA Field Values:\n=================\n");
116     ndx += cp;
117     cp = sprintf(ndx, "   Random Value: %s\n", rand_val == NULL ? "<NULL>" : rand_val);
118     ndx += cp;
119     cp = sprintf(ndx, "       Username: %s\n", username == NULL ? "<NULL>" : username);
120     ndx += cp;
121     cp = sprintf(ndx, "      Timestamp: %u\n", (unsigned int) timestamp);
122     ndx += cp;
123     cp = sprintf(ndx, "    FKO Version: %s\n", version == NULL ? "<NULL>" : version);
124     ndx += cp;
125     cp = sprintf(ndx, "   Message Type: %i\n", msg_type);
126     ndx += cp;
127     cp = sprintf(ndx, " Message String: %s\n", spa_message == NULL ? "<NULL>" : spa_message);
128     ndx += cp;
129     cp = sprintf(ndx, "     Nat Access: %s\n", nat_access == NULL ? "<NULL>" : nat_access);
130     ndx += cp;
131     cp = sprintf(ndx, "    Server Auth: %s\n", server_auth == NULL ? "<NULL>" : server_auth);
132     ndx += cp;
133     cp = sprintf(ndx, " Client Timeout: %u\n", client_timeout);
134     ndx += cp;
135     cp = sprintf(ndx, "    Digest Type: %u\n", digest_type);
136     ndx += cp;
137     cp = sprintf(ndx, "   Encoded Data: %s\n", enc_data == NULL ? "<NULL>" : enc_data);
138     ndx += cp;
139     cp = sprintf(ndx, "SPA Data Digest: %s\n", spa_digest == NULL ? "<NULL>" : spa_digest);
140
141     return(buf);
142 }
143
144 /* Basic directory checks (stat() and whether the path is actually
145  * a directory).
146 */
147 int
148 is_valid_dir(const char *path)
149 {
150 #if HAVE_STAT
151     struct stat st;
152
153     /* If we are unable to stat the given dir, then return with error.
154     */
155     if(stat(path, &st) != 0)
156     {
157         fprintf(stderr, "[-] unable to stat() directory: %s: %s\n",
158             path, strerror(errno));
159         exit(EXIT_FAILURE);
160     }
161
162     if(!S_ISDIR(st.st_mode))
163         return(0);
164 #endif /* HAVE_STAT */
165
166     return(1);
167 }
168
169 int
170 set_file_perms(const char *file)
171 {
172     int res = 0;
173
174     res = chmod(file, S_IRUSR | S_IWUSR);
175
176     if(res != 0)
177     {
178         fprintf(stderr, "[-] unable to chmod file %s to user read/write: %s\n",
179             file, strerror(errno));
180     }
181     return res;
182 }
183
184 int
185 verify_file_perms_ownership(const char *file)
186 {
187     int res = 1;
188 #if HAVE_STAT
189     struct stat st;
190
191     /* Every file that fwknopd deals with should be owned
192      * by the user and permissions set to 600 (user read/write)
193     */
194     if((stat(file, &st)) != 0)
195     {
196         /* if the path doesn't exist, just return, but otherwise something
197          * went wrong
198         */
199         if(errno == ENOENT)
200         {
201             return 0;
202         } else {
203             fprintf(stderr, "[-] stat() against file: %s returned: %s\n",
204                 file, strerror(errno));
205             exit(EXIT_FAILURE);
206         }
207     }
208
209     /* Make sure it is a regular file
210     */
211     if(S_ISREG(st.st_mode) != 1 && S_ISLNK(st.st_mode) != 1)
212     {
213         fprintf(stderr,
214             "[-] file: %s is not a regular file or symbolic link.\n",
215             file
216         );
217         res = 0;
218     }
219
220     if((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != (S_IRUSR|S_IWUSR))
221     {
222         fprintf(stderr,
223             "[-] file: %s permissions should only be user read/write (0600, -rw-------)\n",
224             file
225         );
226         res = 0;
227     }
228
229     if(st.st_uid != getuid())
230     {
231         fprintf(stderr, "[-] file: %s not owned by current effective user id\n",
232             file);
233         res = 0;
234     }
235 #endif
236
237     return res;
238 }
239
240 /* Determine if a buffer contains only characters from the base64
241  * encoding set
242 */
243 int
244 is_base64(const unsigned char *buf, unsigned short int len)
245 {
246     unsigned short int  i;
247     int                 rv = 1;
248
249     for(i=0; i<len; i++)
250     {
251         if(!(isalnum(buf[i]) || buf[i] == '/' || buf[i] == '+' || buf[i] == '='))
252         {
253             rv = 0;
254             break;
255         }
256     }
257
258     return rv;
259 }
260
261 /***EOF***/