1 /*
2 * Python object wrapper of libfwnt_security_identifier_t
3 *
4 * Copyright (C) 2009-2021, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <types.h>
24
25 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
26 #include <stdlib.h>
27 #endif
28
29 #include "pyfwnt_error.h"
30 #include "pyfwnt_libcerror.h"
31 #include "pyfwnt_libfwnt.h"
32 #include "pyfwnt_python.h"
33 #include "pyfwnt_security_identifier.h"
34 #include "pyfwnt_unused.h"
35
36 PyMethodDef pyfwnt_security_identifier_object_methods[] = {
37
38 { "copy_from_byte_stream",
39 (PyCFunction) pyfwnt_security_identifier_copy_from_byte_stream,
40 METH_VARARGS | METH_KEYWORDS,
41 "copy_from_byte_stream(byte_stream)\n"
42 "\n"
43 "Copies the security identifier from the byte stream." },
44
45 { "get_string",
46 (PyCFunction) pyfwnt_security_identifier_get_string,
47 METH_NOARGS,
48 "get_string() -> Unicode string\n"
49 "\n"
50 "Retrieves the security identifier formatted as a string." },
51
52 /* Sentinel */
53 { NULL, NULL, 0, NULL }
54 };
55
56 PyGetSetDef pyfwnt_security_identifier_object_get_set_definitions[] = {
57
58 { "string",
59 (getter) pyfwnt_security_identifier_get_string,
60 (setter) 0,
61 "The string.",
62 NULL },
63
64 /* Sentinel */
65 { NULL, NULL, NULL, NULL, NULL }
66 };
67
68 PyTypeObject pyfwnt_security_identifier_type_object = {
69 PyVarObject_HEAD_INIT( NULL, 0 )
70
71 /* tp_name */
72 "pyfwnt.security_identifier",
73 /* tp_basicsize */
74 sizeof( pyfwnt_security_identifier_t ),
75 /* tp_itemsize */
76 0,
77 /* tp_dealloc */
78 (destructor) pyfwnt_security_identifier_free,
79 /* tp_print */
80 0,
81 /* tp_getattr */
82 0,
83 /* tp_setattr */
84 0,
85 /* tp_compare */
86 0,
87 /* tp_repr */
88 0,
89 /* tp_as_number */
90 0,
91 /* tp_as_sequence */
92 0,
93 /* tp_as_mapping */
94 0,
95 /* tp_hash */
96 0,
97 /* tp_call */
98 0,
99 /* tp_str */
100 0,
101 /* tp_getattro */
102 0,
103 /* tp_setattro */
104 0,
105 /* tp_as_buffer */
106 0,
107 /* tp_flags */
108 Py_TPFLAGS_DEFAULT,
109 /* tp_doc */
110 "pyfwnt security identifier object (wraps libfwnt_security_identifier_t)",
111 /* tp_traverse */
112 0,
113 /* tp_clear */
114 0,
115 /* tp_richcompare */
116 0,
117 /* tp_weaklistoffset */
118 0,
119 /* tp_iter */
120 0,
121 /* tp_iternext */
122 0,
123 /* tp_methods */
124 pyfwnt_security_identifier_object_methods,
125 /* tp_members */
126 0,
127 /* tp_getset */
128 pyfwnt_security_identifier_object_get_set_definitions,
129 /* tp_base */
130 0,
131 /* tp_dict */
132 0,
133 /* tp_descr_get */
134 0,
135 /* tp_descr_set */
136 0,
137 /* tp_dictoffset */
138 0,
139 /* tp_init */
140 (initproc) pyfwnt_security_identifier_init,
141 /* tp_alloc */
142 0,
143 /* tp_new */
144 0,
145 /* tp_free */
146 0,
147 /* tp_is_gc */
148 0,
149 /* tp_bases */
150 NULL,
151 /* tp_mro */
152 NULL,
153 /* tp_cache */
154 NULL,
155 /* tp_subclasses */
156 NULL,
157 /* tp_weaklist */
158 NULL,
159 /* tp_del */
160 0
161 };
162
163 /* Creates a new security identifier object
164 * Returns a Python object if successful or NULL on error
165 */
pyfwnt_security_identifier_new(libfwnt_security_identifier_t * security_identifier,PyObject * parent_object)166 PyObject *pyfwnt_security_identifier_new(
167 libfwnt_security_identifier_t *security_identifier,
168 PyObject *parent_object )
169 {
170 pyfwnt_security_identifier_t *pyfwnt_security_identifier = NULL;
171 static char *function = "pyfwnt_security_identifier_new";
172
173 if( security_identifier == NULL )
174 {
175 PyErr_Format(
176 PyExc_ValueError,
177 "%s: invalid security identifier.",
178 function );
179
180 return( NULL );
181 }
182 /* PyObject_New does not invoke tp_init
183 */
184 pyfwnt_security_identifier = PyObject_New(
185 struct pyfwnt_security_identifier,
186 &pyfwnt_security_identifier_type_object );
187
188 if( pyfwnt_security_identifier == NULL )
189 {
190 PyErr_Format(
191 PyExc_MemoryError,
192 "%s: unable to initialize security identifier.",
193 function );
194
195 goto on_error;
196 }
197 pyfwnt_security_identifier->security_identifier = security_identifier;
198 pyfwnt_security_identifier->parent_object = parent_object;
199
200 if( pyfwnt_security_identifier->parent_object != NULL )
201 {
202 Py_IncRef(
203 pyfwnt_security_identifier->parent_object );
204 }
205 return( (PyObject *) pyfwnt_security_identifier );
206
207 on_error:
208 if( pyfwnt_security_identifier != NULL )
209 {
210 Py_DecRef(
211 (PyObject *) pyfwnt_security_identifier );
212 }
213 return( NULL );
214 }
215
216 /* Initializes a security identifier object
217 * Returns 0 if successful or -1 on error
218 */
pyfwnt_security_identifier_init(pyfwnt_security_identifier_t * pyfwnt_security_identifier)219 int pyfwnt_security_identifier_init(
220 pyfwnt_security_identifier_t *pyfwnt_security_identifier )
221 {
222 libcerror_error_t *error = NULL;
223 static char *function = "pyfwnt_security_identifier_init";
224
225 if( pyfwnt_security_identifier == NULL )
226 {
227 PyErr_Format(
228 PyExc_ValueError,
229 "%s: invalid security identifier.",
230 function );
231
232 return( -1 );
233 }
234 /* Make sure libfwnt security identifier is set to NULL
235 */
236 pyfwnt_security_identifier->security_identifier = NULL;
237
238 if( libfwnt_security_identifier_initialize(
239 &( pyfwnt_security_identifier->security_identifier ),
240 &error ) != 1 )
241 {
242 pyfwnt_error_raise(
243 error,
244 PyExc_MemoryError,
245 "%s: unable to initialize security identifier.",
246 function );
247
248 libcerror_error_free(
249 &error );
250
251 return( -1 );
252 }
253 return( 0 );
254 }
255
256 /* Frees a security identifier object
257 */
pyfwnt_security_identifier_free(pyfwnt_security_identifier_t * pyfwnt_security_identifier)258 void pyfwnt_security_identifier_free(
259 pyfwnt_security_identifier_t *pyfwnt_security_identifier )
260 {
261 struct _typeobject *ob_type = NULL;
262 libcerror_error_t *error = NULL;
263 static char *function = "pyfwnt_security_identifier_free";
264 int result = 0;
265
266 if( pyfwnt_security_identifier == NULL )
267 {
268 PyErr_Format(
269 PyExc_ValueError,
270 "%s: invalid security identifier.",
271 function );
272
273 return;
274 }
275 ob_type = Py_TYPE(
276 pyfwnt_security_identifier );
277
278 if( ob_type == NULL )
279 {
280 PyErr_Format(
281 PyExc_ValueError,
282 "%s: missing ob_type.",
283 function );
284
285 return;
286 }
287 if( ob_type->tp_free == NULL )
288 {
289 PyErr_Format(
290 PyExc_ValueError,
291 "%s: invalid ob_type - missing tp_free.",
292 function );
293
294 return;
295 }
296 if( pyfwnt_security_identifier->security_identifier != NULL )
297 {
298 Py_BEGIN_ALLOW_THREADS
299
300 result = libfwnt_security_identifier_free(
301 &( pyfwnt_security_identifier->security_identifier ),
302 &error );
303
304 Py_END_ALLOW_THREADS
305
306 if( result != 1 )
307 {
308 pyfwnt_error_raise(
309 error,
310 PyExc_MemoryError,
311 "%s: unable to free libfwnt security identifier.",
312 function );
313
314 libcerror_error_free(
315 &error );
316 }
317 }
318 if( pyfwnt_security_identifier->parent_object != NULL )
319 {
320 Py_DecRef(
321 pyfwnt_security_identifier->parent_object );
322 }
323 ob_type->tp_free(
324 (PyObject*) pyfwnt_security_identifier );
325 }
326
327 /* Copies the security identifier from a byte stream
328 * Returns a Python object if successful or NULL on error
329 */
pyfwnt_security_identifier_copy_from_byte_stream(pyfwnt_security_identifier_t * pyfwnt_security_identifier,PyObject * arguments,PyObject * keywords)330 PyObject *pyfwnt_security_identifier_copy_from_byte_stream(
331 pyfwnt_security_identifier_t *pyfwnt_security_identifier,
332 PyObject *arguments,
333 PyObject *keywords )
334 {
335 PyObject *bytes_object = NULL;
336 libcerror_error_t *error = NULL;
337 const char *byte_stream = NULL;
338 static char *function = "pyfwnt_security_identifier_copy_from_byte_stream";
339 static char *keyword_list[] = { "byte_stream", NULL };
340 Py_ssize_t byte_stream_size = 0;
341 int result = 0;
342
343 if( pyfwnt_security_identifier == NULL )
344 {
345 PyErr_Format(
346 PyExc_TypeError,
347 "%s: invalid security identifier.",
348 function );
349
350 return( NULL );
351 }
352 if( PyArg_ParseTupleAndKeywords(
353 arguments,
354 keywords,
355 "O",
356 keyword_list,
357 &bytes_object ) == 0 )
358 {
359 return( NULL );
360 }
361 PyErr_Clear();
362
363 #if PY_MAJOR_VERSION >= 3
364 result = PyObject_IsInstance(
365 bytes_object,
366 (PyObject *) &PyBytes_Type );
367 #else
368 result = PyObject_IsInstance(
369 bytes_object,
370 (PyObject *) &PyString_Type );
371 #endif
372 if( result == -1 )
373 {
374 pyfwnt_error_fetch_and_raise(
375 PyExc_RuntimeError,
376 "%s: unable to determine if object is of type bytes.",
377 function );
378
379 return( NULL );
380 }
381 else if( result == 0 )
382 {
383 PyErr_Format(
384 PyExc_TypeError,
385 "%s: unsupported bytes object type",
386 function );
387
388 return( NULL );
389 }
390 PyErr_Clear();
391
392 #if PY_MAJOR_VERSION >= 3
393 byte_stream = PyBytes_AsString(
394 bytes_object );
395
396 byte_stream_size = PyBytes_Size(
397 bytes_object );
398 #else
399 byte_stream = PyString_AsString(
400 bytes_object );
401
402 byte_stream_size = PyString_Size(
403 bytes_object );
404 #endif
405 if( ( byte_stream_size < 0 )
406 || ( byte_stream_size > (Py_ssize_t) SSIZE_MAX ) )
407 {
408 PyErr_Format(
409 PyExc_ValueError,
410 "%s: invalid byte stream size value out of bounds.",
411 function );
412
413 return( NULL );
414 }
415 Py_BEGIN_ALLOW_THREADS
416
417 result = libfwnt_security_identifier_copy_from_byte_stream(
418 pyfwnt_security_identifier->security_identifier,
419 (uint8_t *) byte_stream,
420 (size_t) byte_stream_size,
421 LIBFWNT_ENDIAN_LITTLE,
422 &error );
423
424 Py_END_ALLOW_THREADS
425
426 if( result != 1 )
427 {
428 pyfwnt_error_raise(
429 error,
430 PyExc_IOError,
431 "%s: unable to copy security identifier from byte stream.",
432 function );
433
434 libcerror_error_free(
435 &error );
436
437 return( NULL );
438 }
439 Py_IncRef(
440 Py_None );
441
442 return( Py_None );
443 }
444
445 /* Retrieves the string
446 * Returns a Python object if successful or NULL on error
447 */
pyfwnt_security_identifier_get_string(pyfwnt_security_identifier_t * pyfwnt_security_identifier,PyObject * arguments PYFWNT_ATTRIBUTE_UNUSED)448 PyObject *pyfwnt_security_identifier_get_string(
449 pyfwnt_security_identifier_t *pyfwnt_security_identifier,
450 PyObject *arguments PYFWNT_ATTRIBUTE_UNUSED )
451 {
452 PyObject *string_object = NULL;
453 libcerror_error_t *error = NULL;
454 const char *errors = NULL;
455 static char *function = "pyfwnt_security_identifier_get_string";
456 char *utf8_string = NULL;
457 size_t string_size = 0;
458 uint32_t string_format_flags = 0;
459 int result = 0;
460
461 PYFWNT_UNREFERENCED_PARAMETER( arguments )
462
463 if( pyfwnt_security_identifier == NULL )
464 {
465 PyErr_Format(
466 PyExc_ValueError,
467 "%s: invalid security identifier.",
468 function );
469
470 return( NULL );
471 }
472 Py_BEGIN_ALLOW_THREADS
473
474 result = libfwnt_security_identifier_get_string_size(
475 pyfwnt_security_identifier->security_identifier,
476 &string_size,
477 string_format_flags,
478 &error );
479
480 Py_END_ALLOW_THREADS
481
482 if( result == -1 )
483 {
484 pyfwnt_error_raise(
485 error,
486 PyExc_IOError,
487 "%s: unable to determine size of string as string.",
488 function );
489
490 libcerror_error_free(
491 &error );
492
493 goto on_error;
494 }
495 else if( ( result == 0 )
496 || ( string_size == 0 ) )
497 {
498 Py_IncRef(
499 Py_None );
500
501 return( Py_None );
502 }
503 utf8_string = (char *) PyMem_Malloc(
504 sizeof( char ) * string_size );
505
506 if( utf8_string == NULL )
507 {
508 PyErr_Format(
509 PyExc_MemoryError,
510 "%s: unable to create UTF-8 string.",
511 function );
512
513 goto on_error;
514 }
515 Py_BEGIN_ALLOW_THREADS
516
517 result = libfwnt_security_identifier_copy_to_utf8_string(
518 pyfwnt_security_identifier->security_identifier,
519 (uint8_t *) utf8_string,
520 string_size,
521 string_format_flags,
522 &error );
523
524 Py_END_ALLOW_THREADS
525
526 if( result != 1 )
527 {
528 pyfwnt_error_raise(
529 error,
530 PyExc_IOError,
531 "%s: unable to retrieve string as UTF-8 string.",
532 function );
533
534 libcerror_error_free(
535 &error );
536
537 goto on_error;
538 }
539 /* Pass the string length to PyUnicode_DecodeUTF8 otherwise it makes
540 * the end of string character is part of the string.
541 */
542 string_object = PyUnicode_DecodeUTF8(
543 utf8_string,
544 (Py_ssize_t) string_size - 1,
545 errors );
546
547 if( string_object == NULL )
548 {
549 PyErr_Format(
550 PyExc_IOError,
551 "%s: unable to convert UTF-8 string into Unicode object.",
552 function );
553
554 goto on_error;
555 }
556 PyMem_Free(
557 utf8_string );
558
559 return( string_object );
560
561 on_error:
562 if( utf8_string != NULL )
563 {
564 PyMem_Free(
565 utf8_string );
566 }
567 return( NULL );
568 }
569
570