+Generates --bug-pathname resources file for sandbox crash bugreport
[captive.git] / src / libcaptive / client / options-module.c
1 /* $Id$
2  * User options handling code of libcaptive
3  * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "captive/options.h"    /* self */
23 #include <glib/gmessages.h>
24 #include "captive/macros.h"
25 #include <glib/gstrfuncs.h>
26 #include <stdlib.h>
27 #include "captive/rtl-file.h"
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <sys/mman.h>
32 #include <openssl/md5.h>
33 #include <openssl/bn.h>
34 #include <openssl/crypto.h>
35
36
37 gboolean captive_options_module_load(struct captive_options_module *options_module,const gchar *pathname_utf8)
38 {
39         g_return_val_if_fail(options_module!=NULL,FALSE);
40         g_return_val_if_fail(pathname_utf8!=NULL,FALSE);
41
42         /* Open the Module */
43         options_module->type=CAPTIVE_OPTIONS_MODULE_TYPE_PE32;
44         options_module->pathname_utf8=g_strdup(pathname_utf8);
45         options_module->u.pe32.mapped=TRUE;
46         options_module->u.pe32.base=captive_rtl_file_mmap(
47                         &options_module->u.pe32.length, /* lenp */
48                         pathname_utf8,  /* path */
49                         O_RDONLY,       /* open_flags */
50                         PROT_READ,      /* mmap_prot */
51                         MAP_SHARED);    /* mmap_flags */
52         /* FIXME: convert errno instead of STATUS_INSUFFICIENT_RESOURCES */
53         g_return_val_if_fail(options_module->u.pe32.base!=NULL,FALSE);
54
55         if (options_module->u.pe32.length>=2
56                         && (('M'<<8U)|('Z'<<0U))==GUINT16_FROM_BE(*(const guint16 *)options_module->u.pe32.base)) {
57 unsigned char md5_bin[1+128/8]; /* 128 bits==16 bytes; '1+' for leading stub to prevent shorter output of BN_bn2hex() */
58 BIGNUM *bignum;
59 char *hex;
60
61                 /* already done above */
62                 /* Calculate MD5 sum and convert it to hex string: */
63                 MD5(options_module->u.pe32.base,options_module->u.pe32.length,md5_bin+1);
64                 md5_bin[0]=0xFF;        /* stub to prevent shorter output of BN_bn2hex() */
65                 bignum=BN_bin2bn(md5_bin,1+128/8,NULL);
66                 hex=BN_bn2hex(bignum);
67                 g_assert(strlen(hex)==2*(1+128/8));
68                 options_module->u.pe32.md5=g_strdup(hex+2);
69                 OPENSSL_free(hex);
70                 BN_free(bignum);
71                 }
72         else {
73                 captive_rtl_file_munmap(options_module->u.pe32.base);
74                 options_module->type=CAPTIVE_OPTIONS_MODULE_TYPE_GMODULE;
75                 options_module->u.gmodule.pathname=g_strdup(pathname_utf8);
76                 }
77
78         return TRUE;
79 }
80
81
82 void captive_options_module_copy(struct captive_options_module *dest,const struct captive_options_module *src)
83 {
84         g_return_if_fail(dest!=NULL);
85         g_return_if_fail(src!=NULL);
86
87         dest->pathname_utf8=g_strdup(src->pathname_utf8);
88
89         dest->type=src->type;
90         switch (src->type) {
91                 case CAPTIVE_OPTIONS_MODULE_TYPE_EMPTY: g_assert_not_reached();
92
93                 case CAPTIVE_OPTIONS_MODULE_TYPE_PE32:
94                         dest->u.pe32.base=g_memdup(src->u.pe32.base,src->u.pe32.length);
95                         dest->u.pe32.length=src->u.pe32.length;
96                         dest->u.pe32.mapped=FALSE;
97                         dest->u.pe32.md5=g_strdup(src->u.pe32.md5);
98                         break;
99
100                 case CAPTIVE_OPTIONS_MODULE_TYPE_GMODULE:
101                         dest->u.gmodule.pathname=g_strdup(src->u.gmodule.pathname);
102                         break;
103
104                 default: g_assert_not_reached();
105                 }
106 }
107
108
109 void captive_options_module_free(struct captive_options_module *options_module)
110 {
111         g_return_if_fail(options_module!=NULL);
112
113         g_free(options_module->pathname_utf8);
114
115         switch (options_module->type) {
116                 case CAPTIVE_OPTIONS_MODULE_TYPE_EMPTY:
117                         break;
118
119                 case CAPTIVE_OPTIONS_MODULE_TYPE_PE32:
120                         if (options_module->u.pe32.mapped)
121                                 captive_rtl_file_munmap(options_module->u.pe32.base);
122                         else
123                                 g_free(options_module->u.pe32.base);
124                         g_free(options_module->u.pe32.md5);
125                         break;
126
127                 case CAPTIVE_OPTIONS_MODULE_TYPE_GMODULE:
128                         g_free(options_module->u.gmodule.pathname);
129                         break;
130
131                 default: g_assert_not_reached();
132                 }
133 }