summaryrefslogtreecommitdiffstats
path: root/typewrappers.h
blob: 8e1998e4d97f2f8f9e71bb8f3fb531ab92a95199 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
 * libvirt_wrap.h: type wrappers for libvir python bindings
 *
 * Copyright (C) 2005 Red Hat, Inc.
 *
 * Daniel Veillard <veillard@redhat.com>
 */

#include <Python.h>
#include "libvirt/libvirt.h"
#include "libvirt/virterror.h"

#ifdef __GNUC__
# ifdef ATTRIBUTE_UNUSED
#  undef ATTRIBUTE_UNUSED
# endif
# ifndef ATTRIBUTE_UNUSED
#  define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
# endif /* ATTRIBUTE_UNUSED */
#else
# define ATTRIBUTE_UNUSED
#endif

#define PyvirConnect_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirConnect_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virConnectPtr obj;
} PyvirConnect_Object;


#define PyvirDomain_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirDomain_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virDomainPtr obj;
} PyvirDomain_Object;


#define PyvirNetwork_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirNetwork_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virNetworkPtr obj;
} PyvirNetwork_Object;


#define PyvirInterface_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirInterface_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virInterfacePtr obj;
} PyvirInterface_Object;


#define PyvirStoragePool_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirStoragePool_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virStoragePoolPtr obj;
} PyvirStoragePool_Object;


#define PyvirStorageVol_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirStorageVol_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virStorageVolPtr obj;
} PyvirStorageVol_Object;


#define PyvirNodeDevice_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirNodeDevice_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virNodeDevicePtr obj;
} PyvirNodeDevice_Object;

#define PyvirSecret_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirSecret_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virSecretPtr obj;
} PyvirSecret_Object;


#define PyvirStream_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirStream_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virStreamPtr obj;
} PyvirStream_Object;


#define PyvirEventHandleCallback_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirEventHandleCallback_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virEventHandleCallback obj;
} PyvirEventHandleCallback_Object;

#define PyvirEventTimeoutCallback_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirEventTimeoutCallback_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virEventTimeoutCallback obj;
} PyvirEventTimeoutCallback_Object;

#define PyvirFreeCallback_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirFreeCallback_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    virFreeCallback obj;
} PyvirFreeCallback_Object;

#define PyvirVoidPtr_Get(v) (((v) == Py_None) ? NULL : \
        (((PyvirVoidPtr_Object *)(v))->obj))

typedef struct {
    PyObject_HEAD
    void* obj;
} PyvirVoidPtr_Object;


PyObject * libvirt_intWrap(int val);
PyObject * libvirt_longWrap(long val);
PyObject * libvirt_ulongWrap(unsigned long val);
PyObject * libvirt_longlongWrap(long long val);
PyObject * libvirt_ulonglongWrap(unsigned long long val);
PyObject * libvirt_charPtrWrap(char *str);
PyObject * libvirt_constcharPtrWrap(const char *str);
PyObject * libvirt_charPtrConstWrap(const char *str);
PyObject * libvirt_virConnectPtrWrap(virConnectPtr node);
PyObject * libvirt_virDomainPtrWrap(virDomainPtr node);
PyObject * libvirt_virNetworkPtrWrap(virNetworkPtr node);
PyObject * libvirt_virInterfacePtrWrap(virInterfacePtr node);
PyObject * libvirt_virStoragePoolPtrWrap(virStoragePoolPtr node);
PyObject * libvirt_virStorageVolPtrWrap(virStorageVolPtr node);
PyObject * libvirt_virEventHandleCallbackWrap(virEventHandleCallback node);
PyObject * libvirt_virEventTimeoutCallbackWrap(virEventTimeoutCallback node);
PyObject * libvirt_virFreeCallbackWrap(virFreeCallback node);
PyObject * libvirt_virVoidPtrWrap(void* node);
PyObject * libvirt_virNodeDevicePtrWrap(virNodeDevicePtr node);
PyObject * libvirt_virSecretPtrWrap(virSecretPtr node);
PyObject * libvirt_virStreamPtrWrap(virStreamPtr node);


/* Provide simple macro statement wrappers (adapted from GLib, in turn from Perl):
 *  LIBVIRT_STMT_START { statements; } LIBVIRT_STMT_END;
 *  can be used as a single statement, as in
 *  if (x) LIBVIRT_STMT_START { ... } LIBVIRT_STMT_END; else ...
 *
 *  When GCC is compiling C code in non-ANSI mode, it will use the
 *  compiler __extension__ to wrap the statements within `({' and '})' braces.
 *  When compiling on platforms where configure has defined
 *  HAVE_DOWHILE_MACROS, statements will be wrapped with `do' and `while (0)'.
 *  For any other platforms (SunOS4 is known to have this issue), wrap the
 *  statements with `if (1)' and `else (void) 0'.
 */
#if !(defined (LIBVIRT_STMT_START) && defined (LIBVIRT_STMT_END))
# if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
#  define LIBVIRT_STMT_START (void) __extension__ (
#  define LIBVIRT_STMT_END )
# else /* !(__GNUC__ && !__STRICT_ANSI__ && !__cplusplus) */
#  if defined (HAVE_DOWHILE_MACROS)
#   define LIBVIRT_STMT_START do
#   define LIBVIRT_STMT_END while (0)
#  else /* !HAVE_DOWHILE_MACROS */
#   define LIBVIRT_STMT_START if (1)
#   define LIBVIRT_STMT_END else (void) 0
#  endif /* !HAVE_DOWHILE_MACROS */
# endif /* !(__GNUC__ && !__STRICT_ANSI__ && !__cplusplus) */
#endif

#define LIBVIRT_BEGIN_ALLOW_THREADS			\
  LIBVIRT_STMT_START {					\
    PyThreadState *_save = NULL;			\
    if (PyEval_ThreadsInitialized())			\
      _save = PyEval_SaveThread();

#define LIBVIRT_END_ALLOW_THREADS                           \
  if (PyEval_ThreadsInitialized())			    \
    PyEval_RestoreThread(_save);			    \
    } LIBVIRT_STMT_END

#define LIBVIRT_ENSURE_THREAD_STATE			\
  LIBVIRT_STMT_START {					\
    PyGILState_STATE _save = PyGILState_UNLOCKED;	\
    if (PyEval_ThreadsInitialized())			\
      _save = PyGILState_Ensure();

#define LIBVIRT_RELEASE_THREAD_STATE                           \
  if (PyEval_ThreadsInitialized())			       \
    PyGILState_Release(_save);				       \
  } LIBVIRT_STMT_END
opt">{ ret = cksum_type->hash->hash(data, num_data, cksum_data); } if (ret == 0) { if (cksum_type->trunc_size) { cksum_data->length = cksum_type->trunc_size; } } cleanup: if (ret != 0) { memset(cksum_data->data, 0, cksum_data->length); } return ret; } const struct krb5_cksumtypes * krb5int_c_find_checksum_type(krb5_cksumtype cksumtype) { size_t i; for (i = 0; i < krb5int_cksumtypes_length; i++) { if (krb5int_cksumtypes_list[i].ctype == cksumtype) break; } if (i == krb5int_cksumtypes_length) return NULL; return &krb5int_cksumtypes_list[i]; } #ifdef DEBUG_IOV static void dump_block(const char *tag, size_t i, size_t j, unsigned char *block, size_t block_size) { size_t k; printf("[%s: %d.%d] ", tag, i, j); for (k = 0; k < block_size; k++) printf("%02x ", block[k] & 0xFF); printf("\n"); } #endif static int process_block_p(const krb5_crypto_iov *data, size_t num_data, struct iov_block_state *iov_state, size_t i) { const krb5_crypto_iov *iov = &data[i]; int process_block; switch (iov->flags) { case KRB5_CRYPTO_TYPE_SIGN_ONLY: process_block = iov_state->include_sign_only; break; case KRB5_CRYPTO_TYPE_PADDING: process_block = (iov_state->pad_to_boundary == 0); break; case KRB5_CRYPTO_TYPE_HEADER: process_block = (iov_state->ignore_header == 0); break; case KRB5_CRYPTO_TYPE_DATA: process_block = 1; break; default: process_block = 0; break; } return process_block; } /* * Returns TRUE if, having reached the end of the current buffer, * we should pad the rest of the block with zeros. */ static int pad_to_boundary_p(const krb5_crypto_iov *data, size_t num_data, struct iov_block_state *iov_state, size_t i, size_t j) { /* If the pad_to_boundary flag is unset, return FALSE */ if (iov_state->pad_to_boundary == 0) return 0; /* If we haven't got any data, we need to get some */ if (j == 0) return 0; /* No boundary between adjacent buffers marked for processing */ if (data[iov_state->iov_pos].flags == data[i].flags) return 0; return 1; } krb5_boolean krb5int_c_iov_get_block(unsigned char *block, size_t block_size, const krb5_crypto_iov *data, size_t num_data, struct iov_block_state *iov_state) { size_t i, j = 0; for (i = iov_state->iov_pos; i < num_data; i++) { const krb5_crypto_iov *iov = &data[i]; size_t nbytes; if (!process_block_p(data, num_data, iov_state, i)) continue; if (pad_to_boundary_p(data, num_data, iov_state, i, j)) break; iov_state->iov_pos = i; nbytes = iov->data.length - iov_state->data_pos; if (nbytes > block_size - j) nbytes = block_size - j; memcpy(block + j, iov->data.data + iov_state->data_pos, nbytes); iov_state->data_pos += nbytes; j += nbytes; assert(j <= block_size); if (j == block_size) break; assert(iov_state->data_pos == iov->data.length); iov_state->data_pos = 0; } iov_state->iov_pos = i; if (i == num_data) return FALSE; if (j != block_size) memset(block + j, 0, block_size - j); #ifdef DEBUG_IOV dump_block("get_block", i, j, block, block_size); #endif return TRUE; } krb5_boolean krb5int_c_iov_put_block(const krb5_crypto_iov *data, size_t num_data, unsigned char *block, size_t block_size, struct iov_block_state *iov_state) { size_t i, j = 0; for (i = iov_state->iov_pos; i < num_data; i++) { const krb5_crypto_iov *iov = &data[i]; size_t nbytes; if (!process_block_p(data, num_data, iov_state, i)) continue; if (pad_to_boundary_p(data, num_data, iov_state, i, j)) break; iov_state->iov_pos = i; nbytes = iov->data.length - iov_state->data_pos; if (nbytes > block_size - j) nbytes = block_size - j; memcpy(iov->data.data + iov_state->data_pos, block + j, nbytes); iov_state->data_pos += nbytes; j += nbytes; assert(j <= block_size); if (j == block_size) break; assert(iov_state->data_pos == iov->data.length); iov_state->data_pos = 0; } iov_state->iov_pos = i; #ifdef DEBUG_IOV dump_block("put_block", i, j, block, block_size); #endif return (iov_state->iov_pos < num_data); } krb5_error_code krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp, krb5_key key, krb5_keyusage keyusage, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) { krb5_error_code ret; unsigned int header_len, trailer_len; krb5_crypto_iov *iov; krb5_crypto_iov *stream; size_t i, j; int got_data = 0; stream = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM); assert(stream != NULL); header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); if (stream->data.length < header_len + trailer_len) return KRB5_BAD_MSIZE; iov = calloc(num_data + 2, sizeof(krb5_crypto_iov)); if (iov == NULL) return ENOMEM; i = 0; iov[i].flags = KRB5_CRYPTO_TYPE_HEADER; /* takes place of STREAM */ iov[i].data = make_data(stream->data.data, header_len); i++; for (j = 0; j < num_data; j++) { if (data[j].flags == KRB5_CRYPTO_TYPE_DATA) { if (got_data) { free(iov); return KRB5_BAD_MSIZE; } got_data++; data[j].data.data = stream->data.data + header_len; data[j].data.length = stream->data.length - header_len - trailer_len; } if (data[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY || data[j].flags == KRB5_CRYPTO_TYPE_DATA) iov[i++] = data[j]; } /* Use empty padding since tokens don't indicate the padding length. */ iov[i].flags = KRB5_CRYPTO_TYPE_PADDING; iov[i].data = empty_data(); i++; iov[i].flags = KRB5_CRYPTO_TYPE_TRAILER; iov[i].data = make_data(stream->data.data + stream->data.length - trailer_len, trailer_len); i++; assert(i <= num_data + 2); ret = ktp->decrypt(ktp, key, keyusage, ivec, iov, i); free(iov); return ret; } unsigned int krb5int_c_padding_length(const struct krb5_keytypes *ktp, size_t data_length) { unsigned int header, padding; /* * Add in the header length since the header is encrypted along with the * data. (arcfour violates this assumption since not all of the header is * encrypted, but that's okay since it has no padding. If there is ever an * enctype using a similar token format and a block cipher, we will have to * move this logic into an enctype-dependent function.) */ header = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); data_length += header; padding = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); if (padding == 0 || (data_length % padding) == 0) return 0; else return padding - (data_length % padding); }