rkerberos 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,312 @@
1
+ #include <rkerberos.h>
2
+
3
+ VALUE cKadm5Config;
4
+
5
+ static void rkadm5_config_free(RUBY_KADM5_CONFIG* ptr){
6
+ if(!ptr)
7
+ return;
8
+
9
+ kadm5_free_config_params(ptr->ctx, &ptr->config);
10
+
11
+ if(ptr->ctx)
12
+ krb5_free_context(ptr->ctx);
13
+
14
+ free(ptr);
15
+ }
16
+
17
+ // Allocation function for the Kerberos::Krb5 class.
18
+ static VALUE rkadm5_config_allocate(VALUE klass){
19
+ RUBY_KADM5_CONFIG* ptr = malloc(sizeof(RUBY_KADM5_CONFIG));
20
+ memset(ptr, 0, sizeof(RUBY_KADM5_CONFIG));
21
+ return Data_Wrap_Struct(klass, 0, rkadm5_config_free, ptr);
22
+ }
23
+
24
+ /*
25
+ * Returns a Kerberos::Kadm5::Config object. This object contains Kerberos
26
+ * admin configuration.
27
+ *
28
+ * Note that the returned object is frozen. Changes made to the Kerberos
29
+ * admin configuration options after the call will not be reflected in this
30
+ * object.
31
+ */
32
+ static VALUE rkadm5_config_initialize(VALUE self){
33
+ RUBY_KADM5_CONFIG* ptr;
34
+ krb5_error_code kerror;
35
+
36
+ Data_Get_Struct(self, RUBY_KADM5_CONFIG, ptr);
37
+
38
+ kerror = krb5_init_context(&ptr->ctx);
39
+
40
+ if(kerror)
41
+ rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
42
+
43
+ kerror = kadm5_get_config_params(
44
+ ptr->ctx,
45
+ 1,
46
+ &ptr->config,
47
+ &ptr->config
48
+ );
49
+
50
+ if(kerror)
51
+ rb_raise(cKrb5Exception, "kadm5_get_config_params: %s", error_message(kerror));
52
+
53
+ if(ptr->config.realm)
54
+ rb_iv_set(self, "@realm", rb_str_new2(ptr->config.realm));
55
+ else
56
+ rb_iv_set(self, "@realm", Qnil);
57
+
58
+ if(ptr->config.admin_server)
59
+ rb_iv_set(self, "@admin_server", rb_str_new2(ptr->config.admin_server));
60
+ else
61
+ rb_iv_set(self, "@admin_server", Qnil);
62
+
63
+ if(ptr->config.kadmind_port)
64
+ rb_iv_set(self, "@kadmind_port", INT2FIX(ptr->config.kadmind_port));
65
+ else
66
+ rb_iv_set(self, "@kadmind_port", Qnil);
67
+
68
+ if(ptr->config.kpasswd_port)
69
+ rb_iv_set(self, "@kpasswd_port", INT2FIX(ptr->config.kpasswd_port));
70
+ else
71
+ rb_iv_set(self, "@kpasswd_port", Qnil);
72
+
73
+ if(ptr->config.admin_keytab)
74
+ rb_iv_set(self, "@admin_keytab", rb_str_new2(ptr->config.admin_keytab));
75
+ else
76
+ rb_iv_set(self, "@admin_keytab", Qnil);
77
+
78
+ if(ptr->config.acl_file)
79
+ rb_iv_set(self, "@acl_file", rb_str_new2(ptr->config.acl_file));
80
+ else
81
+ rb_iv_set(self, "@acl_file", Qnil);
82
+
83
+ if(ptr->config.dict_file)
84
+ rb_iv_set(self, "@dict_file", rb_str_new2(ptr->config.dict_file));
85
+ else
86
+ rb_iv_set(self, "@dict_file", Qnil);
87
+
88
+ if(ptr->config.stash_file)
89
+ rb_iv_set(self, "@stash_file", rb_str_new2(ptr->config.stash_file));
90
+ else
91
+ rb_iv_set(self, "@stash_file", Qnil);
92
+
93
+ if(ptr->config.mkey_name)
94
+ rb_iv_set(self, "@mkey_name", rb_str_new2(ptr->config.mkey_name));
95
+ else
96
+ rb_iv_set(self, "@mkey_name", Qnil);
97
+
98
+ if(ptr->config.mkey_from_kbd)
99
+ rb_iv_set(self, "@mkey_from_kbd", INT2FIX(ptr->config.mkey_from_kbd));
100
+ else
101
+ rb_iv_set(self, "@mkey_from_kbd", Qnil);
102
+
103
+ if(ptr->config.enctype)
104
+ rb_iv_set(self, "@enctype", INT2FIX(ptr->config.enctype));
105
+ else
106
+ rb_iv_set(self, "@enctype", Qnil);
107
+
108
+ if(ptr->config.max_life)
109
+ rb_iv_set(self, "@max_life", INT2FIX(ptr->config.max_life));
110
+ else
111
+ rb_iv_set(self, "@max_life", Qnil);
112
+
113
+ if(ptr->config.max_rlife)
114
+ rb_iv_set(self, "@max_rlife", INT2FIX(ptr->config.max_rlife));
115
+ else
116
+ rb_iv_set(self, "@max_rlife", Qnil);
117
+
118
+ if(ptr->config.expiration)
119
+ rb_iv_set(self, "@expiration", rb_time_new(ptr->config.expiration, 0));
120
+ else
121
+ rb_iv_set(self, "@expiration", Qnil);
122
+
123
+ if(ptr->config.flags)
124
+ rb_iv_set(self, "@flags", INT2FIX(ptr->config.flags));
125
+ else
126
+ rb_iv_set(self, "@flags", Qnil);
127
+
128
+ if(ptr->config.kvno)
129
+ rb_iv_set(self, "@kvno", INT2FIX(ptr->config.kvno));
130
+ else
131
+ rb_iv_set(self, "@kvno", Qnil);
132
+
133
+ if(ptr->config.iprop_enabled)
134
+ rb_iv_set(self, "@iprop_enabled", Qtrue);
135
+ else
136
+ rb_iv_set(self, "@iprop_enabled", Qfalse);
137
+
138
+ if(ptr->config.iprop_logfile)
139
+ rb_iv_set(self, "@iprop_logfile", rb_str_new2(ptr->config.iprop_logfile));
140
+ else
141
+ rb_iv_set(self, "@iprop_logfile", Qnil);
142
+
143
+ if(ptr->config.iprop_poll_time)
144
+ rb_iv_set(self, "@iprop_poll_time", INT2FIX(ptr->config.iprop_poll_time));
145
+ else
146
+ rb_iv_set(self, "@iprop_poll_time", Qnil);
147
+
148
+ if(ptr->config.iprop_port)
149
+ rb_iv_set(self, "@iprop_port", INT2FIX(ptr->config.iprop_port));
150
+ else
151
+ rb_iv_set(self, "@iprop_port", Qnil);
152
+
153
+ if(ptr->config.num_keysalts)
154
+ rb_iv_set(self, "@num_keysalts", INT2FIX(ptr->config.num_keysalts));
155
+ else
156
+ rb_iv_set(self, "@num_keysalts", Qnil);
157
+
158
+ // Not very useful at the moment. How do you iterate over an enum in C?
159
+ if(ptr->config.keysalts)
160
+ rb_iv_set(self, "@keysalts", INT2FIX(ptr->config.keysalts));
161
+ else
162
+ rb_iv_set(self, "@keysalts", Qnil);
163
+
164
+ // This is read only data
165
+ rb_obj_freeze(self);
166
+
167
+ return self;
168
+ }
169
+
170
+ static VALUE rkadm5_config_inspect(VALUE self){
171
+ RUBY_KADM5_CONFIG* ptr;
172
+ VALUE v_str;
173
+
174
+ Data_Get_Struct(self, RUBY_KADM5_CONFIG, ptr);
175
+
176
+ v_str = rb_str_new2("#<");
177
+ rb_str_buf_cat2(v_str, rb_obj_classname(self));
178
+ rb_str_buf_cat2(v_str, " ");
179
+
180
+ rb_str_buf_cat2(v_str, "acl_file=");
181
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@acl_file")));
182
+ rb_str_buf_cat2(v_str, " ");
183
+
184
+ rb_str_buf_cat2(v_str, "admin_keytab=");
185
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@admin_keytab")));
186
+ rb_str_buf_cat2(v_str, " ");
187
+
188
+ rb_str_buf_cat2(v_str, "admin_server=");
189
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@admin_server")));
190
+ rb_str_buf_cat2(v_str, " ");
191
+
192
+ rb_str_buf_cat2(v_str, "dict_file=");
193
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@dict_file")));
194
+ rb_str_buf_cat2(v_str, " ");
195
+
196
+ rb_str_buf_cat2(v_str, "enctype=");
197
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@enctype")));
198
+ rb_str_buf_cat2(v_str, " ");
199
+
200
+ rb_str_buf_cat2(v_str, "expiration=");
201
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@expiration")));
202
+ rb_str_buf_cat2(v_str, " ");
203
+
204
+ rb_str_buf_cat2(v_str, "flags=");
205
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@flags")));
206
+ rb_str_buf_cat2(v_str, " ");
207
+
208
+ rb_str_buf_cat2(v_str, "iprop_enabled=");
209
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@iprop_enabled")));
210
+ rb_str_buf_cat2(v_str, " ");
211
+
212
+ rb_str_buf_cat2(v_str, "iprop_logfile=");
213
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@iprop_logfile")));
214
+ rb_str_buf_cat2(v_str, " ");
215
+
216
+ rb_str_buf_cat2(v_str, "iprop_poll_time=");
217
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@iprop_poll_time")));
218
+ rb_str_buf_cat2(v_str, " ");
219
+
220
+ rb_str_buf_cat2(v_str, "iprop_port=");
221
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@iprop_port")));
222
+ rb_str_buf_cat2(v_str, " ");
223
+
224
+ rb_str_buf_cat2(v_str, "kadmind_port=");
225
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@kadmind_port")));
226
+ rb_str_buf_cat2(v_str, " ");
227
+
228
+ rb_str_buf_cat2(v_str, "keysalts=");
229
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@keysalts")));
230
+ rb_str_buf_cat2(v_str, " ");
231
+
232
+ rb_str_buf_cat2(v_str, "kpasswd_port=");
233
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@kpasswd_port")));
234
+ rb_str_buf_cat2(v_str, " ");
235
+
236
+ rb_str_buf_cat2(v_str, "kvno=");
237
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@kvno")));
238
+ rb_str_buf_cat2(v_str, " ");
239
+
240
+ rb_str_buf_cat2(v_str, "mkey_name=");
241
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@mkey_name")));
242
+ rb_str_buf_cat2(v_str, " ");
243
+
244
+ rb_str_buf_cat2(v_str, "mkey_from_kbd=");
245
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@mkey_from_kbd")));
246
+ rb_str_buf_cat2(v_str, " ");
247
+
248
+ rb_str_buf_cat2(v_str, "maxlife=");
249
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@maxlife")));
250
+ rb_str_buf_cat2(v_str, " ");
251
+
252
+ rb_str_buf_cat2(v_str, "maxrlife=");
253
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@maxrlife")));
254
+ rb_str_buf_cat2(v_str, " ");
255
+
256
+ rb_str_buf_cat2(v_str, "num_keysalts=");
257
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@num_keysalts")));
258
+ rb_str_buf_cat2(v_str, " ");
259
+
260
+ rb_str_buf_cat2(v_str, "realm=");
261
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@realm")));
262
+ rb_str_buf_cat2(v_str, " ");
263
+
264
+ rb_str_buf_cat2(v_str, "stash_file=");
265
+ rb_str_buf_append(v_str, rb_inspect(rb_iv_get(self, "@stash_file")));
266
+ rb_str_buf_cat2(v_str, " ");
267
+
268
+ rb_str_buf_cat2(v_str, ">");
269
+
270
+ return v_str;
271
+ }
272
+
273
+ void Init_config(){
274
+ cKadm5Config = rb_define_class_under(cKadm5, "Config", rb_cObject);
275
+
276
+ // Allocation function
277
+
278
+ rb_define_alloc_func(cKadm5Config, rkadm5_config_allocate);
279
+
280
+ // Initializer
281
+
282
+ rb_define_method(cKadm5Config, "initialize", rkadm5_config_initialize, 0);
283
+
284
+ // Methods
285
+
286
+ rb_define_method(cKadm5Config, "inspect", rkadm5_config_inspect, 0);
287
+
288
+ // Accessors
289
+
290
+ rb_define_attr(cKadm5Config, "acl_file", 1, 0);
291
+ rb_define_attr(cKadm5Config, "admin_keytab", 1, 0);
292
+ rb_define_attr(cKadm5Config, "admin_server", 1, 0);
293
+ rb_define_attr(cKadm5Config, "dict_file", 1, 0);
294
+ rb_define_attr(cKadm5Config, "enctype", 1, 0);
295
+ rb_define_attr(cKadm5Config, "expiration", 1, 0);
296
+ rb_define_attr(cKadm5Config, "flags", 1, 0);
297
+ rb_define_attr(cKadm5Config, "iprop_enabled", 1, 0);
298
+ rb_define_attr(cKadm5Config, "iprop_logfile", 1, 0);
299
+ rb_define_attr(cKadm5Config, "iprop_poll_time", 1, 0);
300
+ rb_define_attr(cKadm5Config, "iprop_port", 1, 0);
301
+ rb_define_attr(cKadm5Config, "kadmind_port", 1, 0);
302
+ rb_define_attr(cKadm5Config, "keysalts", 1, 0);
303
+ rb_define_attr(cKadm5Config, "kpasswd_port", 1, 0);
304
+ rb_define_attr(cKadm5Config, "kvno", 1, 0);
305
+ rb_define_attr(cKadm5Config, "mkey_name", 1, 0);
306
+ rb_define_attr(cKadm5Config, "mkey_from_kbd", 1, 0);
307
+ rb_define_attr(cKadm5Config, "max_life", 1, 0);
308
+ rb_define_attr(cKadm5Config, "max_rlife", 1, 0);
309
+ rb_define_attr(cKadm5Config, "num_keysalts", 1, 0);
310
+ rb_define_attr(cKadm5Config, "realm", 1, 0);
311
+ rb_define_attr(cKadm5Config, "stash_file", 1, 0);
312
+ }
@@ -0,0 +1,77 @@
1
+ #include <rkerberos.h>
2
+
3
+ VALUE cKrb5Context;
4
+
5
+ // Free function for the Kerberos::Krb5::Context class.
6
+ static void rkrb5_context_free(RUBY_KRB5_CONTEXT* ptr){
7
+ if(!ptr)
8
+ return;
9
+
10
+ if(ptr->ctx)
11
+ krb5_free_context(ptr->ctx);
12
+
13
+ free(ptr);
14
+ }
15
+
16
+ // Allocation function for the Kerberos::Krb5::Context class.
17
+ static VALUE rkrb5_context_allocate(VALUE klass){
18
+ RUBY_KRB5_CONTEXT* ptr = malloc(sizeof(RUBY_KRB5_CONTEXT));
19
+ memset(ptr, 0, sizeof(RUBY_KRB5_CONTEXT));
20
+ return Data_Wrap_Struct(klass, 0, rkrb5_context_free, ptr);
21
+ }
22
+
23
+ /*
24
+ * call-seq:
25
+ * context.close
26
+ *
27
+ * Closes the context object.
28
+ */
29
+ static VALUE rkrb5_context_close(VALUE self){
30
+ RUBY_KRB5_CONTEXT* ptr;
31
+
32
+ Data_Get_Struct(self, RUBY_KRB5_CONTEXT, ptr);
33
+
34
+ if(ptr->ctx)
35
+ krb5_free_context(ptr->ctx);
36
+
37
+ ptr->ctx = NULL;
38
+
39
+ return self;
40
+ }
41
+
42
+ /*
43
+ * call-seq:
44
+ * Kerberos::Context.new
45
+ *
46
+ * Creates and returns a new Kerberos::Context object.
47
+ *
48
+ * This class is not typically instantiated directly, but is used internally
49
+ * by the krb5-auth library.
50
+ */
51
+ static VALUE rkrb5_context_initialize(VALUE self){
52
+ RUBY_KRB5_CONTEXT* ptr;
53
+ krb5_error_code kerror;
54
+
55
+ Data_Get_Struct(self, RUBY_KRB5_CONTEXT, ptr);
56
+
57
+ kerror = krb5_init_context(&ptr->ctx);
58
+
59
+ if(kerror)
60
+ rb_raise(cKrb5Exception, "krb5_init_context: %s", error_message(kerror));
61
+
62
+ return self;
63
+ }
64
+
65
+ void Init_context(){
66
+ /* The Kerberos::Krb5::Context class encapsulates a Kerberos context. */
67
+ cKrb5Context = rb_define_class_under(cKrb5, "Context", rb_cObject);
68
+
69
+ // Allocation Function
70
+ rb_define_alloc_func(cKrb5Context, rkrb5_context_allocate);
71
+
72
+ // Constructor
73
+ rb_define_method(cKrb5Context, "initialize", rkrb5_context_initialize, 0);
74
+
75
+ // Instance Methods
76
+ rb_define_method(cKrb5Context, "close", rkrb5_context_close, 0);
77
+ }
@@ -0,0 +1,14 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('rkerberos', '/usr/local')
4
+
5
+ have_header('krb5.h')
6
+ have_library('krb5')
7
+
8
+ if have_header('kadm5/admin.h')
9
+ have_library('kadm5clnt')
10
+ else
11
+ raise "kadm5clnt library not found"
12
+ end
13
+
14
+ create_makefile('rkerberos')
@@ -0,0 +1,991 @@
1
+ #include <rkerberos.h>
2
+
3
+ VALUE cKadm5;
4
+ VALUE cKadm5Exception;
5
+ VALUE cKadm5PrincipalNotFoundException;
6
+
7
+ // Prototype
8
+ static VALUE rkadm5_close(VALUE);
9
+
10
+ // Free function for the Kerberos::Kadm5 class.
11
+ static void rkadm5_free(RUBY_KADM5* ptr){
12
+ if(!ptr)
13
+ return;
14
+
15
+ if(ptr->princ)
16
+ krb5_free_principal(ptr->ctx, ptr->princ);
17
+
18
+ if(ptr->ctx)
19
+ krb5_free_context(ptr->ctx);
20
+
21
+ free(ptr);
22
+ }
23
+
24
+ // Allocation function for the Kerberos::Kadm5 class.
25
+ static VALUE rkadm5_allocate(VALUE klass){
26
+ RUBY_KADM5* ptr = malloc(sizeof(RUBY_KADM5));
27
+ memset(ptr, 0, sizeof(RUBY_KADM5));
28
+ return Data_Wrap_Struct(klass, 0, rkadm5_free, ptr);
29
+ }
30
+
31
+ /*
32
+ * call-seq:
33
+ * Kerberos::Kadm5.new(:principal => 'name', :password => 'xxxxx')
34
+ * Kerberos::Kadm5.new(:principal => 'name', :keytab => '/path/to/your/keytab')
35
+ * Kerberos::Kadm5.new(:principal => 'name', :keytab => true)
36
+ *
37
+ * Creates and returns a new Kerberos::Kadm5 object. A hash argument is
38
+ * accepted that allows you to specify a principal and a password, or
39
+ * a keytab file.
40
+ *
41
+ * If you pass a string as the :keytab value it will attempt to use that file
42
+ * for the keytab. If you pass true as the value it will attempt to use the
43
+ * default keytab file, typically /etc/krb5.keytab.
44
+ *
45
+ * You may also pass the :service option to specify the service name. The
46
+ * default is kadmin/admin.
47
+ */
48
+ static VALUE rkadm5_initialize(VALUE self, VALUE v_opts){
49
+ RUBY_KADM5* ptr;
50
+ VALUE v_principal, v_password, v_keytab, v_service;
51
+ char* user;
52
+ char* pass = NULL;
53
+ char* keytab = NULL;
54
+ char* service = NULL;
55
+ krb5_error_code kerror;
56
+
57
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
58
+ Check_Type(v_opts, T_HASH);
59
+
60
+ v_principal = rb_hash_aref2(v_opts, "principal");
61
+
62
+ // Principal must be specified
63
+ if(NIL_P(v_principal))
64
+ rb_raise(rb_eArgError, "principal must be specified");
65
+
66
+ Check_Type(v_principal, T_STRING);
67
+ user = StringValuePtr(v_principal);
68
+
69
+ v_password = rb_hash_aref2(v_opts, "password");
70
+ v_keytab = rb_hash_aref2(v_opts, "keytab");
71
+
72
+ if(RTEST(v_password) && RTEST(v_keytab))
73
+ rb_raise(rb_eArgError, "cannot use both a password and a keytab");
74
+
75
+ if(RTEST(v_password)){
76
+ Check_Type(v_password, T_STRING);
77
+ pass = StringValuePtr(v_password);
78
+ }
79
+
80
+ v_service = rb_hash_aref2(v_opts, "service");
81
+
82
+ if(NIL_P(v_service)){
83
+ service = "kadmin/admin";
84
+ }
85
+ else{
86
+ Check_Type(v_service, T_STRING);
87
+ service = StringValuePtr(v_service);
88
+ }
89
+
90
+ // Normally I would wait to initialize the context, but we might need it
91
+ // to get the default keytab file name.
92
+ kerror = krb5_init_context(&ptr->ctx);
93
+
94
+ if(kerror)
95
+ rb_raise(cKadm5Exception, "krb5_init_context: %s", error_message(kerror));
96
+
97
+ // The docs say I can use NULL to get the default, but reality appears to be otherwise.
98
+ if(RTEST(v_keytab)){
99
+ if(TYPE(v_keytab) == T_TRUE){
100
+ char default_name[MAX_KEYTAB_NAME_LEN];
101
+
102
+ kerror = krb5_kt_default_name(ptr->ctx, default_name, MAX_KEYTAB_NAME_LEN);
103
+
104
+ if(kerror)
105
+ rb_raise(cKrb5Exception, "krb5_kt_default_name: %s", error_message(kerror));
106
+
107
+ keytab = default_name;
108
+ }
109
+ else{
110
+ Check_Type(v_keytab, T_STRING);
111
+ keytab = StringValuePtr(v_keytab);
112
+ }
113
+ }
114
+
115
+ if(RTEST(v_password)){
116
+ #ifdef KADM5_API_VERSION_3
117
+ kerror = kadm5_init_with_password(
118
+ ptr->ctx,
119
+ user,
120
+ pass,
121
+ service,
122
+ NULL,
123
+ KADM5_STRUCT_VERSION,
124
+ KADM5_API_VERSION_3,
125
+ NULL,
126
+ &ptr->handle
127
+ );
128
+ #else
129
+ kerror = kadm5_init_with_password(
130
+ user,
131
+ pass,
132
+ service,
133
+ NULL,
134
+ KADM5_STRUCT_VERSION,
135
+ KADM5_API_VERSION_2,
136
+ NULL,
137
+ &ptr->handle
138
+ );
139
+ #endif
140
+
141
+ if(kerror)
142
+ rb_raise(cKadm5Exception, "kadm5_init_with_password: %s", error_message(kerror));
143
+ }
144
+ else if(RTEST(v_keytab)){
145
+ #ifdef KADM5_API_VERSION_3
146
+ kerror = kadm5_init_with_skey(
147
+ ptr->ctx,
148
+ user,
149
+ keytab,
150
+ service,
151
+ NULL,
152
+ KADM5_STRUCT_VERSION,
153
+ KADM5_API_VERSION_3,
154
+ NULL,
155
+ &ptr->handle
156
+ );
157
+ #else
158
+ kerror = kadm5_init_with_skey(
159
+ user,
160
+ keytab,
161
+ service,
162
+ NULL,
163
+ KADM5_STRUCT_VERSION,
164
+ KADM5_API_VERSION_2,
165
+ NULL,
166
+ &ptr->handle
167
+ );
168
+ #endif
169
+
170
+ if(kerror)
171
+ rb_raise(cKadm5Exception, "kadm5_init_with_skey: %s", error_message(kerror));
172
+ }
173
+ else{
174
+ // TODO: Credentials cache.
175
+ }
176
+
177
+ if(rb_block_given_p()){
178
+ rb_ensure(rb_yield, self, rkadm5_close, self);
179
+ return Qnil;
180
+ }
181
+
182
+ return self;
183
+ }
184
+
185
+ /* call-seq:
186
+ * kadm5.set_password(user, password)
187
+ *
188
+ * Set the password for +user+ (i.e. the principal) to +password+.
189
+ */
190
+ static VALUE rkadm5_set_password(VALUE self, VALUE v_user, VALUE v_pass){
191
+ Check_Type(v_user, T_STRING);
192
+ Check_Type(v_pass, T_STRING);
193
+
194
+ RUBY_KADM5* ptr;
195
+ char* user = StringValuePtr(v_user);
196
+ char* pass = StringValuePtr(v_pass);
197
+ krb5_error_code kerror;
198
+
199
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
200
+
201
+ if(!ptr->ctx)
202
+ rb_raise(cKadm5Exception, "no context has been established");
203
+
204
+ kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ);
205
+
206
+ if(kerror)
207
+ rb_raise(cKadm5Exception, "krb5_parse_name: %s", error_message(kerror));
208
+
209
+ kerror = kadm5_chpass_principal(ptr->handle, ptr->princ, pass);
210
+
211
+ if(kerror)
212
+ rb_raise(cKadm5Exception, "kadm5_chpass_principal: %s", error_message(kerror));
213
+
214
+ return self;
215
+ }
216
+
217
+ /*
218
+ * call-seq:
219
+ * kadm5.create_principal(name, password)
220
+ * kadm5.create_principal(principal)
221
+ *
222
+ * Creates a new principal +name+ with an initial password of +password+.
223
+ *--
224
+ * TODO: Allow a Principal object to be passed in as an argument.
225
+ */
226
+ static VALUE rkadm5_create_principal(VALUE self, VALUE v_user, VALUE v_pass){
227
+ RUBY_KADM5* ptr;
228
+ char* user;
229
+ char* pass;
230
+ int mask;
231
+ kadm5_principal_ent_rec princ;
232
+ krb5_error_code kerror;
233
+
234
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
235
+
236
+ Check_Type(v_user, T_STRING);
237
+ Check_Type(v_pass, T_STRING);
238
+
239
+ memset(&princ, 0, sizeof(princ));
240
+
241
+ mask = KADM5_PRINCIPAL;
242
+ user = StringValuePtr(v_user);
243
+ pass = StringValuePtr(v_pass);
244
+
245
+ if(!ptr->ctx)
246
+ rb_raise(cKadm5Exception, "no context has been established");
247
+
248
+ kerror = krb5_parse_name(ptr->ctx, user, &princ.principal);
249
+
250
+ if(kerror)
251
+ rb_raise(cKadm5Exception, "krb5_parse_name: %s", error_message(kerror));
252
+
253
+ kerror = kadm5_create_principal(ptr->handle, &princ, mask, pass);
254
+
255
+ if(kerror)
256
+ rb_raise(cKadm5Exception, "kadm5_create_principal: %s", error_message(kerror));
257
+
258
+ krb5_free_principal(ptr->ctx, princ.principal);
259
+
260
+ return self;
261
+ }
262
+
263
+ /* call-seq:
264
+ * kadm5.delete_principal(name)
265
+ *
266
+ * Deletes the principal +name+ from the Kerberos database.
267
+ */
268
+ static VALUE rkadm5_delete_principal(VALUE self, VALUE v_user){
269
+ RUBY_KADM5* ptr;
270
+ char* user;
271
+ krb5_error_code kerror;
272
+
273
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
274
+ Check_Type(v_user, T_STRING);
275
+ user = StringValuePtr(v_user);
276
+
277
+ if(!ptr->ctx)
278
+ rb_raise(cKadm5Exception, "no context has been established");
279
+
280
+ kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ);
281
+
282
+ if(kerror)
283
+ rb_raise(cKadm5Exception, "krb5_parse_name: %s", error_message(kerror));
284
+
285
+ kerror = kadm5_delete_principal(ptr->handle, ptr->princ);
286
+
287
+ if(kerror)
288
+ rb_raise(cKadm5Exception, "kadm5_delete_principal: %s", error_message(kerror));
289
+
290
+ return self;
291
+ }
292
+
293
+ /*
294
+ * call-seq:
295
+ * kadm5.close
296
+ *
297
+ * Closes the kadm5 object. Specifically, it frees the principal and context
298
+ * associated with the kadm5 object, as well as the server handle.
299
+ *
300
+ * Any attempt to call a method on a kadm5 object after it has been closed
301
+ * will fail with an error message indicating a lack of context.
302
+ */
303
+ static VALUE rkadm5_close(VALUE self){
304
+ RUBY_KADM5* ptr;
305
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
306
+
307
+ if(ptr->princ)
308
+ krb5_free_principal(ptr->ctx, ptr->princ);
309
+
310
+ if(ptr->ctx)
311
+ krb5_free_context(ptr->ctx);
312
+
313
+ if(ptr->handle)
314
+ kadm5_destroy(ptr->handle);
315
+
316
+ ptr->ctx = NULL;
317
+ ptr->princ = NULL;
318
+ ptr->handle = NULL;
319
+
320
+ return self;
321
+ }
322
+
323
+ // Private function for creating a Principal object from a entry record.
324
+ static VALUE create_principal_from_entry(VALUE v_name, RUBY_KADM5* ptr, kadm5_principal_ent_rec* ent){
325
+ krb5_error_code kerror;
326
+ VALUE v_principal;
327
+ VALUE v_args[1];
328
+
329
+ v_args[0] = v_name;
330
+
331
+ v_principal = rb_class_new_instance(1, v_args, cKrb5Principal);
332
+
333
+ rb_iv_set(v_principal, "@attributes", LONG2FIX(ent->attributes));
334
+ rb_iv_set(v_principal, "@aux_attributes", INT2FIX(ent->aux_attributes));
335
+
336
+ if(ent->princ_expire_time)
337
+ rb_iv_set(v_principal, "@expire_time", rb_time_new(ent->princ_expire_time, 0));
338
+
339
+ rb_iv_set(v_principal, "@fail_auth_count", INT2FIX(ent->fail_auth_count));
340
+ rb_iv_set(v_principal, "@kvno", INT2FIX(ent->kvno));
341
+
342
+ if(ent->last_failed)
343
+ rb_iv_set(v_principal, "@last_failed", rb_time_new(ent->last_failed, 0));
344
+
345
+ if(ent->last_failed)
346
+ rb_iv_set(v_principal, "@last_password_change", rb_time_new(ent->last_pwd_change, 0));
347
+
348
+ if(ent->last_failed)
349
+ rb_iv_set(v_principal, "@last_success", rb_time_new(ent->last_success, 0));
350
+
351
+ rb_iv_set(v_principal, "@max_life", LONG2FIX(ent->max_life));
352
+ rb_iv_set(v_principal, "@max_renewable_life", LONG2FIX(ent->max_renewable_life));
353
+
354
+ if(ent->mod_date)
355
+ rb_iv_set(v_principal, "@mod_date", rb_time_new(ent->mod_date, 0));
356
+
357
+ if(ent->mod_name){
358
+ char* mod_name;
359
+ kerror = krb5_unparse_name(ptr->ctx, ent->mod_name, &mod_name);
360
+
361
+ if(kerror)
362
+ rb_raise(cKadm5Exception, "krb5_unparse_name: %s", error_message(kerror));
363
+
364
+ rb_iv_set(v_principal, "@mod_name", rb_str_new2(mod_name));
365
+ }
366
+
367
+ if(ent->pw_expiration)
368
+ rb_iv_set(v_principal, "@password_expiration", rb_time_new(ent->pw_expiration, 0));
369
+
370
+ if(ent->policy)
371
+ rb_iv_set(v_principal, "policy", rb_str_new2(ent->policy));
372
+
373
+ return v_principal;
374
+ }
375
+
376
+ /*
377
+ * call-seq:
378
+ * kadm5.find_principal(principal_name)
379
+ *
380
+ * Returns a Principal object for +principal_name+ containing various bits
381
+ * of information regarding that principal, such as policy, attributes,
382
+ * expiration information, etc.
383
+ *
384
+ * Unlike the get_principal method, this method returns nil if the principal
385
+ * cannot be found instead of raising an error.
386
+ */
387
+ static VALUE rkadm5_find_principal(VALUE self, VALUE v_user){
388
+ RUBY_KADM5* ptr;
389
+ VALUE v_principal;
390
+ char* user;
391
+ int mask;
392
+ kadm5_principal_ent_rec ent;
393
+ krb5_error_code kerror;
394
+
395
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
396
+ Check_Type(v_user, T_STRING);
397
+ user = StringValuePtr(v_user);
398
+
399
+ memset(&ent, 0, sizeof(ent));
400
+
401
+ if(!ptr->ctx)
402
+ rb_raise(cKadm5Exception, "no context has been established");
403
+
404
+ kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ);
405
+
406
+ if(kerror)
407
+ rb_raise(cKadm5Exception, "krb5_parse_name: %s", error_message(kerror));
408
+
409
+ mask = KADM5_PRINCIPAL_NORMAL_MASK;
410
+
411
+ kerror = kadm5_get_principal(
412
+ ptr->handle,
413
+ ptr->princ,
414
+ &ent,
415
+ mask
416
+ );
417
+
418
+ // Return nil if not found instead of raising an error.
419
+ if(kerror){
420
+ if(kerror == KADM5_UNK_PRINC)
421
+ v_principal = Qnil;
422
+ else
423
+ rb_raise(cKadm5Exception, "kadm5_get_principal: %s", error_message(kerror));
424
+ }
425
+ else{
426
+ v_principal = create_principal_from_entry(v_user, ptr, &ent);
427
+ }
428
+
429
+ return v_principal;
430
+ }
431
+
432
+ /*
433
+ * call-seq:
434
+ * kadm5.get_principal(principal_name)
435
+ *
436
+ * Returns a Principal object for +principal_name+ containing various bits
437
+ * of information regarding that principal, such as policy, attributes,
438
+ * expiration information, etc.
439
+ *
440
+ * If the +principal_name+ cannot be found then a PrincipalNotFoundException
441
+ * is raised.
442
+ */
443
+ static VALUE rkadm5_get_principal(VALUE self, VALUE v_user){
444
+ RUBY_KADM5* ptr;
445
+ VALUE v_principal;
446
+ char* user;
447
+ int mask;
448
+ kadm5_principal_ent_rec ent;
449
+ krb5_error_code kerror;
450
+
451
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
452
+ Check_Type(v_user, T_STRING);
453
+ user = StringValuePtr(v_user);
454
+
455
+ memset(&ent, 0, sizeof(ent));
456
+
457
+ if(!ptr->ctx)
458
+ rb_raise(cKadm5Exception, "no context has been established");
459
+
460
+ kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ);
461
+
462
+ if(kerror)
463
+ rb_raise(cKadm5Exception, "krb5_parse_name: %s", error_message(kerror));
464
+
465
+ mask = KADM5_PRINCIPAL_NORMAL_MASK;
466
+
467
+ kerror = kadm5_get_principal(
468
+ ptr->handle,
469
+ ptr->princ,
470
+ &ent,
471
+ mask
472
+ );
473
+
474
+ if(kerror){
475
+ if(kerror == KADM5_UNK_PRINC)
476
+ rb_raise(cKadm5PrincipalNotFoundException, "principal not found");
477
+ else
478
+ rb_raise(cKadm5Exception, "kadm5_get_principal: %s", error_message(kerror));
479
+ }
480
+
481
+ v_principal = create_principal_from_entry(v_user, ptr, &ent);
482
+
483
+ return v_principal;
484
+ }
485
+
486
+ /*
487
+ * call-seq:
488
+ * kadm5.create_policy(policy)
489
+ *
490
+ * Creates a new Kerberos policy based on the Policy object.
491
+ *
492
+ * Example:
493
+ *
494
+ * # Using a Policy object
495
+ * policy = Kerberos::Kadm5::Policy.new(:name => 'test', :min_length => 5)
496
+ * kadm5.create_policy(policy)
497
+ *
498
+ * # Using a hash
499
+ * kadm5.create_policy(:name => 'test', :min_length => 5)
500
+ */
501
+ static VALUE rkadm5_create_policy(VALUE self, VALUE v_policy){
502
+ RUBY_KADM5* ptr;
503
+ kadm5_ret_t kerror;
504
+ kadm5_policy_ent_rec ent;
505
+ long mask = KADM5_POLICY;
506
+ VALUE v_name, v_min_classes, v_min_life, v_max_life, v_min_length, v_history_num;
507
+
508
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
509
+
510
+ // Allow a hash or a Policy object
511
+ if(rb_obj_is_kind_of(v_policy, rb_cHash)){
512
+ VALUE v_args[1];
513
+ v_args[0] = v_policy;
514
+ v_policy = rb_class_new_instance(1, v_args, cKadm5Policy);
515
+ }
516
+
517
+ v_name = rb_iv_get(v_policy, "@policy");
518
+ v_min_classes = rb_iv_get(v_policy, "@min_classes");
519
+ v_min_length = rb_iv_get(v_policy, "@min_length");
520
+ v_min_life = rb_iv_get(v_policy, "@min_life");
521
+ v_max_life = rb_iv_get(v_policy, "@max_life");
522
+ v_history_num = rb_iv_get(v_policy, "@history_num");
523
+
524
+ ent.policy = StringValuePtr(v_name);
525
+
526
+ if(RTEST(v_min_classes)){
527
+ mask |= KADM5_PW_MIN_CLASSES;
528
+ ent.pw_min_classes = NUM2LONG(v_min_classes);
529
+ }
530
+
531
+ if(RTEST(v_min_length)){
532
+ mask |= KADM5_PW_MIN_LENGTH;
533
+ ent.pw_min_length = NUM2LONG(v_min_length);
534
+ }
535
+
536
+ if(RTEST(v_min_life)){
537
+ mask |= KADM5_PW_MIN_LIFE;
538
+ ent.pw_min_life = NUM2LONG(v_min_life);
539
+ }
540
+
541
+ if(RTEST(v_max_life)){
542
+ mask |= KADM5_PW_MAX_LIFE;
543
+ ent.pw_max_life = NUM2LONG(v_max_life);
544
+ }
545
+
546
+ if(RTEST(v_history_num)){
547
+ mask |= KADM5_PW_HISTORY_NUM;
548
+ ent.pw_max_life = NUM2LONG(v_history_num);
549
+ }
550
+
551
+ kerror = kadm5_create_policy(ptr->handle, &ent, mask);
552
+
553
+ if(kerror)
554
+ rb_raise(cKadm5Exception, "kadm5_create_policy: %s (%li)", error_message(kerror), kerror);
555
+
556
+ return self;
557
+ }
558
+
559
+ /*
560
+ * call-seq:
561
+ * kadm5.delete_policy(name)
562
+ *
563
+ * Deletes the Kerberos policy +name+.
564
+ *
565
+ * Example:
566
+ *
567
+ * kadm5.delete_policy('test')
568
+ */
569
+ static VALUE rkadm5_delete_policy(VALUE self, VALUE v_policy){
570
+ RUBY_KADM5* ptr;
571
+ kadm5_ret_t kerror;
572
+ char* policy;
573
+
574
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
575
+
576
+ policy = StringValuePtr(v_policy);
577
+
578
+ kerror = kadm5_delete_policy(ptr->handle, policy);
579
+
580
+ if(kerror)
581
+ rb_raise(cKadm5Exception, "kadm5_delete_policy: %s (%li)", error_message(kerror), kerror);
582
+
583
+ return self;
584
+ }
585
+
586
+ /*
587
+ * call-seq:
588
+ * kadm5.get_policy(name)
589
+ *
590
+ * Get and return a Policy object for +name+. If the +name+ cannot be found,
591
+ * then an exception is raised.
592
+ *
593
+ * This method is nearly identical to kadm5.find_policy, except that method
594
+ * returns nil if not found.
595
+ */
596
+ static VALUE rkadm5_get_policy(VALUE self, VALUE v_name){
597
+ RUBY_KADM5* ptr;
598
+ VALUE v_policy = Qnil;
599
+ kadm5_policy_ent_rec ent;
600
+ kadm5_ret_t kerror;
601
+ char* policy_name;
602
+
603
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
604
+ memset(&ent, 0, sizeof(ent));
605
+
606
+ if(!ptr->ctx)
607
+ rb_raise(cKadm5Exception, "no context has been established");
608
+
609
+ policy_name = StringValuePtr(v_name);
610
+
611
+ kerror = kadm5_get_policy(ptr->handle, policy_name, &ent);
612
+
613
+ if(kerror){
614
+ rb_raise(
615
+ cKadm5Exception,
616
+ "kadm5_get_policy: %s (%li)", error_message(kerror), kerror
617
+ );
618
+ }
619
+ else{
620
+ VALUE v_arg[1];
621
+ VALUE v_hash = rb_hash_new();
622
+
623
+ rb_hash_aset(v_hash, rb_str_new2("name"), rb_str_new2(ent.policy));
624
+ rb_hash_aset(v_hash, rb_str_new2("min_life"), LONG2FIX(ent.pw_min_life));
625
+ rb_hash_aset(v_hash, rb_str_new2("max_life"), LONG2FIX(ent.pw_max_life));
626
+ rb_hash_aset(v_hash, rb_str_new2("min_length"), LONG2FIX(ent.pw_min_length));
627
+ rb_hash_aset(v_hash, rb_str_new2("min_classes"), LONG2FIX(ent.pw_min_classes));
628
+ rb_hash_aset(v_hash, rb_str_new2("history_num"), LONG2FIX(ent.pw_history_num));
629
+
630
+ v_arg[0] = v_hash;
631
+
632
+ v_policy = rb_class_new_instance(1, v_arg, cKadm5Policy);
633
+ }
634
+
635
+ return v_policy;
636
+ }
637
+
638
+ /*
639
+ * call-seq:
640
+ * kadm5.find_policy(name)
641
+ *
642
+ * Get and return a Policy object for +name+. If the +name+ cannot be found,
643
+ * then nil is returned.
644
+ *
645
+ * This method is nearly identical to kadm5.get_policy, except that method
646
+ * raises an exception if not found.
647
+ */
648
+ static VALUE rkadm5_find_policy(VALUE self, VALUE v_name){
649
+ RUBY_KADM5* ptr;
650
+ VALUE v_policy = Qnil;
651
+ kadm5_policy_ent_rec ent;
652
+ kadm5_ret_t kerror;
653
+ char* policy_name;
654
+
655
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
656
+ memset(&ent, 0, sizeof(ent));
657
+
658
+ if(!ptr->ctx)
659
+ rb_raise(cKadm5Exception, "no context has been established");
660
+
661
+ policy_name = StringValuePtr(v_name);
662
+
663
+ kerror = kadm5_get_policy(ptr->handle, policy_name, &ent);
664
+
665
+ // Return nil if not found rather than raising an error.
666
+ if(kerror){
667
+ if(kerror != KADM5_UNK_POLICY){
668
+ rb_raise(
669
+ cKadm5Exception,
670
+ "kadm5_get_policy: %s (%li)", error_message(kerror), kerror
671
+ );
672
+ }
673
+ }
674
+ else{
675
+ VALUE v_arg[1];
676
+ VALUE v_hash = rb_hash_new();
677
+
678
+ rb_hash_aset(v_hash, rb_str_new2("name"), rb_str_new2(ent.policy));
679
+ rb_hash_aset(v_hash, rb_str_new2("min_life"), LONG2FIX(ent.pw_min_life));
680
+ rb_hash_aset(v_hash, rb_str_new2("max_life"), LONG2FIX(ent.pw_max_life));
681
+ rb_hash_aset(v_hash, rb_str_new2("min_length"), LONG2FIX(ent.pw_min_length));
682
+ rb_hash_aset(v_hash, rb_str_new2("min_classes"), LONG2FIX(ent.pw_min_classes));
683
+ rb_hash_aset(v_hash, rb_str_new2("history_num"), LONG2FIX(ent.pw_history_num));
684
+
685
+ v_arg[0] = v_hash;
686
+
687
+ v_policy = rb_class_new_instance(1, v_arg, cKadm5Policy);
688
+ }
689
+
690
+ return v_policy;
691
+ }
692
+
693
+ /*
694
+ * call-seq:
695
+ * kadm5.modify_policy(policy)
696
+ *
697
+ * Modify an existing Kerberos policy using a +policy+ object.
698
+ *
699
+ * Example:
700
+ *
701
+ * policy = Kerberos::Kadm5::Policy.find('test')
702
+ * policy.max_length = 1024
703
+ * kadm5.modify_policy(policy)
704
+ */
705
+ static VALUE rkadm5_modify_policy(VALUE self, VALUE v_policy){
706
+ RUBY_KADM5* ptr;
707
+ RUBY_KADM5_POLICY* pptr;
708
+ kadm5_ret_t kerror;
709
+ long mask = KADM5_POLICY;
710
+
711
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
712
+ Data_Get_Struct(v_policy, RUBY_KADM5_POLICY, pptr);
713
+
714
+ if(!ptr->ctx)
715
+ rb_raise(cKadm5Exception, "no context has been established");
716
+
717
+ if(pptr->policy.pw_min_classes)
718
+ mask |= KADM5_PW_MIN_CLASSES;
719
+
720
+ if(pptr->policy.pw_min_length)
721
+ mask |= KADM5_PW_MIN_LENGTH;
722
+
723
+ if(pptr->policy.pw_min_life)
724
+ mask |= KADM5_PW_MIN_LIFE;
725
+
726
+ if(pptr->policy.pw_max_life)
727
+ mask |= KADM5_PW_MAX_LIFE;
728
+
729
+ kerror = kadm5_modify_policy(ptr->handle, &pptr->policy, mask);
730
+
731
+ if(kerror)
732
+ rb_raise(cKadm5Exception, "kadm5_modify_policy: %s (%li)", error_message(kerror), kerror);
733
+
734
+ return self;
735
+ }
736
+
737
+ /*
738
+ * call-seq:
739
+ * kadm5.get_policies(expr = nil)
740
+ *
741
+ * Returns a list of policy names matching +expr+, or all policy names if
742
+ * +expr+ is nil.
743
+ *
744
+ * The valid characters for +expr+ are '*', '?', '[]' and '\'. All other
745
+ * characters match themselves.
746
+ *
747
+ * kadm5.get_policies # => Get all policies
748
+ * kadm5.get_policies('test*') # => Get all policies that start with 'test'
749
+ */
750
+ static VALUE rkadm5_get_policies(int argc, VALUE* argv, VALUE self){
751
+ RUBY_KADM5* ptr;
752
+ VALUE v_array, v_expr;
753
+ kadm5_ret_t kerror;
754
+ char** pols;
755
+ char* expr;
756
+ int i, count;
757
+
758
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
759
+
760
+ rb_scan_args(argc, argv, "01", &v_expr);
761
+
762
+ if(NIL_P(v_expr))
763
+ expr = NULL;
764
+ else
765
+ expr = StringValuePtr(v_expr);
766
+
767
+ kerror = kadm5_get_policies(ptr->handle, expr, &pols, &count);
768
+
769
+ if(kerror)
770
+ rb_raise(cKadm5Exception, "kadm5_get_policies: %s (%li)", error_message(kerror), kerror);
771
+
772
+ v_array = rb_ary_new();
773
+
774
+ for(i = 0; i < count; i++){
775
+ rb_ary_push(v_array, rb_str_new2(pols[i]));
776
+ }
777
+
778
+ kadm5_free_name_list(ptr->handle, pols, count);
779
+
780
+ return v_array;
781
+ }
782
+
783
+ /*
784
+ * call-seq:
785
+ * kadm5.get_principals(expr = nil)
786
+ *
787
+ * Returns a list of principals matching +expr+, or all principals if
788
+ * +expr+ is nil.
789
+ *
790
+ * The valid characters for +expr+ are '*', '?', '[]' and '\'. All other
791
+ * characters match themselves.
792
+ *
793
+ * Example:
794
+ *
795
+ * kadm5.get_principals # => Get all principals
796
+ * kadm5.get_principals('test*') # => Get all principals that start with 'test'
797
+ */
798
+ static VALUE rkadm5_get_principals(int argc, VALUE* argv, VALUE self){
799
+ RUBY_KADM5* ptr;
800
+ VALUE v_array, v_expr;
801
+ kadm5_ret_t kerror;
802
+ char** princs;
803
+ char* expr;
804
+ int i, count;
805
+
806
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
807
+
808
+ rb_scan_args(argc, argv, "01", &v_expr);
809
+
810
+ if(NIL_P(v_expr))
811
+ expr = NULL;
812
+ else
813
+ expr = StringValuePtr(v_expr);
814
+
815
+ kerror = kadm5_get_principals(ptr->handle, expr, &princs, &count);
816
+
817
+ if(kerror)
818
+ rb_raise(cKadm5Exception, "kadm5_get_principals: %s (%li)", error_message(kerror), kerror);
819
+
820
+ v_array = rb_ary_new();
821
+
822
+ for(i = 0; i < count; i++){
823
+ rb_ary_push(v_array, rb_str_new2(princs[i]));
824
+ }
825
+
826
+ kadm5_free_name_list(ptr->handle, princs, count);
827
+
828
+ return v_array;
829
+ }
830
+
831
+ /*
832
+ * call-seq:
833
+ * kadm5.get_privileges(:strings => false)
834
+ *
835
+ * Returns a numeric bitmask indicating the caller's privileges. If the
836
+ * +strings+ option is true, then an array of human readable strings are
837
+ * returned instead.
838
+ *
839
+ * The possible values, and their string equivalent, are:
840
+ *
841
+ * KADM5_PRIV_GET (0x01) => "GET"
842
+ * KADM5_PRIV_ADD (0x02) => "ADD"
843
+ * KADM5_PRIV_MODIFY (0x04) => "MODIFY"
844
+ * KADM5_PRIV_DELETE (0x08) => "DELETE"
845
+ */
846
+ static VALUE rkadm5_get_privs(int argc, VALUE* argv, VALUE self){
847
+ RUBY_KADM5* ptr;
848
+ VALUE v_return = Qnil;
849
+ VALUE v_strings = Qfalse;
850
+ kadm5_ret_t kerror;
851
+ int i;
852
+ long privs;
853
+ int result = 0;
854
+
855
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
856
+
857
+ rb_scan_args(argc, argv, "01", &v_strings);
858
+
859
+ kerror = kadm5_get_privs(ptr->handle, &privs);
860
+
861
+ if(kerror)
862
+ rb_raise(cKadm5Exception, "kadm5_get_privs: %s (%li)", error_message(kerror), kerror);
863
+
864
+ if(RTEST(v_strings)){
865
+ v_return = rb_ary_new();
866
+
867
+ for(i = 0; i < sizeof(privs); i++){
868
+ result |= (privs & 1 << i);
869
+ switch(privs & 1 << i){
870
+ case KADM5_PRIV_GET:
871
+ rb_ary_push(v_return, rb_str_new2("GET"));
872
+ break;
873
+ case KADM5_PRIV_ADD:
874
+ rb_ary_push(v_return, rb_str_new2("ADD"));
875
+ break;
876
+ case KADM5_PRIV_MODIFY:
877
+ rb_ary_push(v_return, rb_str_new2("MODIFY"));
878
+ break;
879
+ case KADM5_PRIV_DELETE:
880
+ rb_ary_push(v_return, rb_str_new2("DELETE"));
881
+ break;
882
+ default:
883
+ rb_ary_push(v_return, rb_str_new2("UNKNOWN"));
884
+ };
885
+ }
886
+ }
887
+ else{
888
+ for(i = 0; i < sizeof(privs); i++){
889
+ result |= (privs & 1 << i);
890
+ }
891
+ v_return = INT2FIX(result);
892
+ }
893
+
894
+ return v_return;
895
+ }
896
+
897
+ /*
898
+ * call-seq:
899
+ * kadm.generate_random_key(principal)
900
+ *
901
+ * Generates and assigns a new random key to the named +principal+ and
902
+ * returns the number of generated keys.
903
+ */
904
+ static VALUE rkadm5_randkey_principal(VALUE self, VALUE v_user){
905
+ RUBY_KADM5* ptr;
906
+ krb5_keyblock* keys;
907
+ kadm5_ret_t kerror;
908
+ krb5_principal princ;
909
+ char* user;
910
+ int n_keys, i;
911
+
912
+ Data_Get_Struct(self, RUBY_KADM5, ptr);
913
+
914
+ user = StringValuePtr(v_user);
915
+
916
+ if(!ptr->ctx)
917
+ rb_raise(cKadm5Exception, "no context has been established");
918
+
919
+ kerror = krb5_parse_name(ptr->ctx, user, &princ);
920
+
921
+ if(kerror)
922
+ rb_raise(cKadm5Exception, "krb5_parse_name: %s", error_message(kerror));
923
+
924
+ kerror = kadm5_randkey_principal(ptr->handle, princ, &keys, &n_keys);
925
+
926
+ if(kerror)
927
+ rb_raise(cKadm5Exception, "kadm5_randkey_principal: %s (%li)", error_message(kerror), kerror);
928
+
929
+ for(i = 0; i < n_keys; i++)
930
+ krb5_free_keyblock_contents(ptr->ctx, &keys[i]);
931
+
932
+ free(keys);
933
+
934
+ return INT2NUM(n_keys);
935
+ }
936
+
937
+ void Init_kadm5(){
938
+ /* The Kadm5 class encapsulates administrative Kerberos functions. */
939
+ cKadm5 = rb_define_class_under(mKerberos, "Kadm5", rb_cObject);
940
+
941
+ /* Error typically raised if any of the Kadm5 methods fail. */
942
+ cKadm5Exception = rb_define_class_under(cKadm5, "Exception", rb_eStandardError);
943
+
944
+ /* Error raised if a get_principal call cannot find the principal. */
945
+ cKadm5PrincipalNotFoundException = rb_define_class_under(
946
+ cKadm5, "PrincipalNotFoundException", rb_eStandardError
947
+ );
948
+
949
+ // Allocation Functions
950
+
951
+ rb_define_alloc_func(cKadm5, rkadm5_allocate);
952
+
953
+ // Initialization Method
954
+
955
+ rb_define_method(cKadm5, "initialize", rkadm5_initialize, 1);
956
+
957
+ // Instance Methods
958
+
959
+ rb_define_method(cKadm5, "close", rkadm5_close, 0);
960
+ rb_define_method(cKadm5, "create_policy", rkadm5_create_policy, 1);
961
+ rb_define_method(cKadm5, "create_principal", rkadm5_create_principal, 2);
962
+ rb_define_method(cKadm5, "delete_policy", rkadm5_delete_policy, 1);
963
+ rb_define_method(cKadm5, "delete_principal", rkadm5_delete_principal, 1);
964
+ rb_define_method(cKadm5, "find_principal", rkadm5_find_principal, 1);
965
+ rb_define_method(cKadm5, "find_policy", rkadm5_find_policy, 1);
966
+ rb_define_method(cKadm5, "generate_random_key", rkadm5_randkey_principal, 1);
967
+ rb_define_method(cKadm5, "get_policy", rkadm5_get_policy, 1);
968
+ rb_define_method(cKadm5, "get_policies", rkadm5_get_policies, -1);
969
+ rb_define_method(cKadm5, "get_principal", rkadm5_get_principal, 1);
970
+ rb_define_method(cKadm5, "get_principals", rkadm5_get_principals, -1);
971
+ rb_define_method(cKadm5, "get_privileges", rkadm5_get_privs, -1);
972
+ rb_define_method(cKadm5, "modify_policy", rkadm5_modify_policy, 1);
973
+ rb_define_method(cKadm5, "set_password", rkadm5_set_password, 2);
974
+
975
+ // Constants
976
+
977
+ rb_define_const(cKadm5, "DISALLOW_POSTDATED", INT2FIX(KRB5_KDB_DISALLOW_POSTDATED));
978
+ rb_define_const(cKadm5, "DISALLOW_FORWARDABLE", INT2FIX(KRB5_KDB_DISALLOW_FORWARDABLE));
979
+ rb_define_const(cKadm5, "DISALLOW_TGT_BASED", INT2FIX(KRB5_KDB_DISALLOW_TGT_BASED));
980
+ rb_define_const(cKadm5, "DISALLOW_RENEWABLE", INT2FIX(KRB5_KDB_DISALLOW_RENEWABLE));
981
+ rb_define_const(cKadm5, "DISALLOW_PROXIABLE", INT2FIX(KRB5_KDB_DISALLOW_PROXIABLE));
982
+ rb_define_const(cKadm5, "DISALLOW_DUP_SKEY", INT2FIX(KRB5_KDB_DISALLOW_DUP_SKEY));
983
+ rb_define_const(cKadm5, "DISALLOW_ALL_TIX", INT2FIX(KRB5_KDB_DISALLOW_ALL_TIX));
984
+ rb_define_const(cKadm5, "REQUIRES_PRE_AUTH", INT2FIX(KRB5_KDB_REQUIRES_PRE_AUTH));
985
+ rb_define_const(cKadm5, "REQUIRES_HW_AUTH", INT2FIX(KRB5_KDB_REQUIRES_HW_AUTH));
986
+ rb_define_const(cKadm5, "REQUIRES_PWCHANGE", INT2FIX(KRB5_KDB_REQUIRES_PWCHANGE));
987
+ rb_define_const(cKadm5, "DISALLOW_SVR", INT2FIX(KRB5_KDB_DISALLOW_SVR));
988
+ rb_define_const(cKadm5, "PWCHANGE_SERVICE", INT2FIX(KRB5_KDB_PWCHANGE_SERVICE));
989
+ rb_define_const(cKadm5, "SUPPORT_DESMD5", INT2FIX(KRB5_KDB_SUPPORT_DESMD5));
990
+ rb_define_const(cKadm5, "NEW_PRINC", INT2FIX(KRB5_KDB_NEW_PRINC));
991
+ }