rkerberos 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }