CUBRID Engine  latest
authenticate.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * authenticate.c - Authorization manager
21  */
22 
23 #ident "$Id$"
24 
25 /*
26  * Note:
27  * Need to remove calls to the db_ layer since there are some
28  * nasty dependency problems during restart and when the server
29  * crashes since we need to touch objects before the database is
30  * officially open.
31  */
32 
33 #include "config.h"
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include <assert.h>
40 
41 #include "porting.h"
42 #include "misc_string.h"
43 #include "memory_alloc.h"
44 #include "dbtype.h"
45 #include "error_manager.h"
46 #include "boot_cl.h"
47 #include "work_space.h"
48 #include "object_primitive.h"
49 #include "class_object.h"
50 #include "schema_manager.h"
51 #include "authenticate.h"
52 #include "set_object.h"
53 #include "object_accessor.h"
54 #include "encryption.h"
55 #include "crypt_opfunc.h"
56 #include "message_catalog.h"
57 #include "string_opfunc.h"
58 #include "locator_cl.h"
59 #include "virtual_object.h"
60 #include "db.h"
61 #include "trigger_manager.h"
62 #include "transform.h"
63 #include "environment_variable.h"
64 #include "execute_schema.h"
65 #include "jsp_cl.h"
66 #include "object_print.h"
67 #include "execute_statement.h"
68 #include "optimizer.h"
69 #include "network_interface_cl.h"
70 #include "printer.hpp"
71 
72 #if defined (SUPPRESS_STRLEN_WARNING)
73 #define strlen(s1) ((int) strlen(s1))
74 #endif /* defined (SUPPRESS_STRLEN_WARNING) */
75 
76 #if defined(SA_MODE)
77 extern bool catcls_Enable;
78 #endif /* SA_MODE */
79 
80 /*
81  * Message id in the set MSGCAT_SET_AUTHORIZATION
82  * in the message catalog MSGCAT_CATALOG_CUBRID (file cubrid.msg).
83  */
84 #define MSGCAT_AUTH_INVALID_CACHE 1
85 #define MSGCAT_AUTH_CLASS_NAME 2
86 #define MSGCAT_AUTH_FROM_USER 3
87 #define MSGCAT_AUTH_USER_TITLE 4
88 #define MSGCAT_AUTH_UNDEFINED_USER 5
89 #define MSGCAT_AUTH_USER_NAME 6
90 #define MSGCAT_AUTH_USER_ID 7
91 #define MSGCAT_AUTH_USER_MEMBERS 8
92 #define MSGCAT_AUTH_USER_GROUPS 9
93 #define MSGCAT_AUTH_USER_NAME2 10
94 #define MSGCAT_AUTH_CURRENT_USER 11
95 #define MSGCAT_AUTH_ROOT_TITLE 12
96 #define MSGCAT_AUTH_ROOT_USERS 13
97 #define MSGCAT_AUTH_GRANT_DUMP_ERROR 14
98 #define MSGCAT_AUTH_AUTH_TITLE 15
99 #define MSGCAT_AUTH_USER_DIRECT_GROUPS 16
100 
101 /*
102  * Authorization Class Names
103  */
104 const char *AU_ROOT_CLASS_NAME = "db_root";
105 const char *AU_OLD_ROOT_CLASS_NAME = "db_authorizations";
106 
107 const char *AU_USER_CLASS_NAME = "db_user";
108 const char *AU_PASSWORD_CLASS_NAME = "db_password";
109 const char *AU_AUTH_CLASS_NAME = "db_authorization";
110 const char *AU_GRANT_CLASS_NAME = "db_grant";
111 
112 const char *AU_PUBLIC_USER_NAME = "PUBLIC";
113 const char *AU_DBA_USER_NAME = "DBA";
114 
115 
116 /*
117  * Grant set structure
118  *
119  * Note :
120  * Grant information is stored packed in a sequence. These
121  * macros define the length of the "elements" of the sequence and the
122  * offsets to particular fields in each element. Previously, grants
123  * were stored in their own object but that lead to serious performance
124  * problems as we tried to load each grant object from the server.
125  * This way, grants are stored in the set directly with the authorization
126  * object so only one fetch is required.
127  *
128  */
129 
130 #define GRANT_ENTRY_LENGTH 3
131 #define GRANT_ENTRY_CLASS(index) (index )
132 #define GRANT_ENTRY_SOURCE(index) ((index) + 1)
133 #define GRANT_ENTRY_CACHE(index) ((index) + 2)
134 
135 #define PASSWORD_ENCRYPTION_SEED "U9a$y1@zw~a0%"
136 #define ENCODE_PREFIX_DEFAULT (char)0
137 #define ENCODE_PREFIX_DES (char)1
138 #define ENCODE_PREFIX_SHA1 (char)2
139 #define ENCODE_PREFIX_SHA2_512 (char)3
140 #define IS_ENCODED_DES(string) (string[0] == ENCODE_PREFIX_DES)
141 #define IS_ENCODED_SHA1(string) (string[0] == ENCODE_PREFIX_SHA1)
142 #define IS_ENCODED_SHA2_512(string) (string[0] == ENCODE_PREFIX_SHA2_512)
143 #define IS_ENCODED_ANY(string) \
144  (IS_ENCODED_SHA2_512 (string) || IS_ENCODED_SHA1 (string) || IS_ENCODED_DES (string))
145 
146 /* Macro to determine if a dbvalue is a character strign type. */
147 #define IS_STRING(n) DB_IS_STRING (n)
148 
149 /* Macro to determine if a name is system catalog class */
150 #define IS_CATALOG_CLASS(name) \
151  (strcmp(name, CT_CLASS_NAME) == 0 || \
152  strcmp(name, CT_ATTRIBUTE_NAME) == 0 || \
153  strcmp(name, CT_DOMAIN_NAME) == 0 || \
154  strcmp(name, CT_METHOD_NAME) == 0 || \
155  strcmp(name, CT_METHSIG_NAME) == 0 || \
156  strcmp(name, CT_METHARG_NAME) == 0 || \
157  strcmp(name, CT_METHFILE_NAME) == 0 || \
158  strcmp(name, CT_QUERYSPEC_NAME) == 0 || \
159  strcmp(name, CT_RESOLUTION_NAME) ==0 || \
160  strcmp(name, CT_INDEX_NAME) == 0 || \
161  strcmp(name, CT_INDEXKEY_NAME) == 0 || \
162  strcmp(name, CT_CLASSAUTH_NAME) == 0 || \
163  strcmp(name, CT_DATATYPE_NAME) == 0 || \
164  strcmp(name, CT_STORED_PROC_NAME) == 0 || \
165  strcmp(name, CT_STORED_PROC_ARGS_NAME) == 0 || \
166  strcmp(name, CT_PARTITION_NAME) == 0 || \
167  strcmp(name, CT_SERIAL_NAME) == 0 || \
168  strcmp(name, CT_USER_NAME) == 0 || \
169  strcmp(name, CT_COLLATION_NAME) == 0 || \
170  strcmp(name, CT_HA_APPLY_INFO_NAME) == 0 || \
171  strcmp(name, CT_TRIGGER_NAME) == 0 || \
172  strcmp(name, CT_ROOT_NAME) == 0 || \
173  strcmp(name, CT_PASSWORD_NAME) == 0 || \
174  strcmp(name, CT_AUTHORIZATION_NAME) == 0 || \
175  strcmp(name, CT_AUTHORIZATIONS_NAME) == 0 || \
176  strcmp(name, CT_CHARSET_NAME) == 0 || \
177  strcmp(name, CT_DUAL_NAME) == 0)
178 
180 {
181  DONT_KNOW, /* Don't know the mop is a class os an instance */
182  BY_INSTANCE_MOP, /* fetch a class by an instance mop */
183  BY_CLASS_MOP /* fetch a class by the class mop */
184 };
185 typedef enum fetch_by FETCH_BY;
186 
187 /*
188  * AU_GRANT
189  *
190  * This is an internal structure used to calculate the recursive
191  * effects of a revoke operation.
192  */
193 typedef struct au_grant AU_GRANT;
194 struct au_grant
195 {
196  struct au_grant *next;
197 
201 
204 
206  int legal;
207 };
208 
209 /*
210  * AU_CLASS_CACHE
211  *
212  * This structure is attached to classes and provides a cache of
213  * the authorization bits. Once authorization is calculated by examining
214  * the group/grant hierarchy, the combined vector of bits is stored
215  * in the cache for faster access.
216  * In releases prior to 2.0, this was a single vector of bits for the
217  * active user. With the introduction of views, it became necessary
218  * to relatively quickly perform a "setuid" operation to switch
219  * authorization contexts within methods accessed through a view.
220  * Because of this, the cache has been extended to be a variable length
221  * array of entries, indexed by a user identifier.
222  */
225 {
227 
229  unsigned int data[1];
230 };
231 
232 /*
233  * AU_USER_CACHE
234  *
235  * This is used to maintain a list of the users that have been
236  * registered into the authorization caches. Each time a "setuid" is
237  * performed, the requested user is added to the caches if it is
238  * not already present.
239  */
242 {
244 
246  int index;
247 };
248 
249 /*
250  * CLASS_GRANT
251  *
252  * Maintains information about a desired grant request.
253  */
254 typedef struct class_grant CLASS_GRANT;
256 {
257  struct class_grant *next;
258 
259  struct class_user *user;
260  int cache;
261 };
262 
263 /*
264  * CLASS_USER
265  *
266  * Maintains information about a desired grant subject user.
267  */
268 typedef struct class_user CLASS_USER;
270 {
271  struct class_user *next;
272 
274 
277 };
278 
279 /*
280  * CLASS_AUTH
281  *
282  * Maintains information about the grants on a particular class.
283  */
284 typedef struct class_auth CLASS_AUTH;
286 {
287 
291 };
292 
293 /*
294  * Au_root
295  *
296  * Global MOP of the authorization root object.
297  * This is cached here after the database is restarted so we don't
298  * have to keep looking for it.
299  */
301 
302 /*
303  * Au_disable
304  *
305  * Flag to disable authorization checking. Only for well behaved
306  * internal system functions. Should not set this directly,
307  * use the AU_DISABLE, AU_ENABLE macros instead.
308  */
309 int Au_disable = 1;
310 
311 /*
312  * Au_ignore_passwords
313  *
314  * When this flag is set, the authorization system will ignore passwords
315  * when logging in users. This is intended for use only be system
316  * defined utility programs that want to run as the DBA user but don't
317  * want to require a password entry each time. These would be protected
318  * through OS file protected by the DBA rather than by the database
319  * authorization mechanism.
320  * This initializes to zero and is changed only by calling the function
321  * au_enable_system_login().
322  */
323 static int Au_ignore_passwords = 0;
324 
325 /*
326  * Au_dba_user, Au_public_user
327  *
328  * These are the two system defined user objects.
329  * All users are automatically a member of the PUBLIC user and hence
330  * grants to PUBLIC are visible to everyone. The DBA is automatically
331  * a member of all groups/users and hence will have all permissions.
332  */
335 
336 /*
337  * Au_user
338  *
339  * This points to the MOP of the user object of the currently
340  * logged in user. Can be overridden in special cases to change
341  * system authorizations.
342  */
344 
345 /*
346  * Au_user_name, Au_user_password
347  *
348  * Saves the registered user name and password.
349  * Login normally ocurrs before the database is restarted so all we
350  * do is register the user name. The user name will be validated
351  * against the database at the time of restart.
352  * Once the database has been started, we get the user information
353  * directly from the user object and no longer use these variables.
354  *
355  * NOTE: Need to be storing the password in an encrypted string.
356  */
357 static char Au_user_name[DB_MAX_USER_LENGTH + 4] = { '\0' };
361 
362 /*
363  * Au_password_class
364  *
365  * This is a hack until we get a proper "system" authorization
366  * level. We need to detect attempts to update or delete
367  * system classes by the DBA when there is no approved
368  * direct update mechanism. This is the case for all the
369  * authorization classes. The only way they can be updated is
370  * through the authorization functions or methods.
371  * To avoid searching for these classes all the time, cache
372  * them here.
373  */
378 
379 /*
380  * Au_user_cache
381  *
382  * The list of cached users.
383  */
385 
386 /*
387  * Au_class_caches
388  *
389  * A list of all allocated class caches. These are maintained on a list
390  * so that we can get to all of them easily when they need to be
391  * altered.
392  */
394 
395 /*
396  * Au_cache_depth
397  *
398  * These maintain information about the structure of the class caches.
399  * Au_cache_depth has largest current index.
400  * Au_cache_max has the total size of the allocated arrays.
401  * Au_cache_increment has the growth count when the array needs to be
402  * extended.
403  * The caches are usually allocated larger than actually necessary so
404  * we can avoid reallocating all of them when a new user is added.
405  * Probably not that big a deal.
406  */
407 static int Au_cache_depth = 0;
408 static int Au_cache_max = 0;
409 static int Au_cache_increment = 4;
410 
411 /*
412  * Au_cache_index
413  *
414  * This is the current index into the class authorization caches.
415  * It will be maintained in parallel with the current user.
416  * Each user is assigned a particular index, when the user changes,
417  * Au_cache_index is changed as well.
418  */
419 static int Au_cache_index = -1;
420 
421 static const char *auth_type_name[] = {
422  "select", "insert", "update", "delete", "alter", "index", "execute"
423 };
424 
425 
426 /* 'get_attribute_number' is a statically linked method used only for QA
427  scenario */
428 void get_attribute_number (DB_OBJECT * target, DB_VALUE * result, DB_VALUE * attr_name);
429 
430 
431 /*
432  * au_static_links
433  *
434  * Since authorization is always linked in with the database, the
435  * methods are defined statically. The linkage will be done
436  * during au_init even though it is redundant on subsequent
437  * restart calls.
438  */
440  {"au_add_user_method", (METHOD_LINK_FUNCTION) au_add_user_method},
441  {"au_drop_user_method", (METHOD_LINK_FUNCTION) au_drop_user_method},
442  {"au_find_user_method", (METHOD_LINK_FUNCTION) au_find_user_method},
443  {"au_add_member_method", (METHOD_LINK_FUNCTION) au_add_member_method},
444  {"au_drop_member_method", (METHOD_LINK_FUNCTION) au_drop_member_method},
445  {"au_set_password_method", (METHOD_LINK_FUNCTION) au_set_password_method},
446  {"au_set_password_encoded_method", (METHOD_LINK_FUNCTION) au_set_password_encoded_method},
447  {"au_set_password_encoded_sha1_method", (METHOD_LINK_FUNCTION) au_set_password_encoded_sha1_method},
448  {"au_describe_user_method", (METHOD_LINK_FUNCTION) au_describe_user_method},
449  {"au_describe_root_method", (METHOD_LINK_FUNCTION) au_describe_root_method},
450  {"au_info_method", (METHOD_LINK_FUNCTION) au_info_method},
451  {"au_login_method", (METHOD_LINK_FUNCTION) au_login_method},
452  {"au_change_owner_method", (METHOD_LINK_FUNCTION) au_change_owner_method},
453  {"au_change_trigger_owner_method", (METHOD_LINK_FUNCTION) au_change_trigger_owner_method},
454  {"au_get_owner_method", (METHOD_LINK_FUNCTION) au_get_owner_method},
455  {"au_check_authorization_method", (METHOD_LINK_FUNCTION) au_check_authorization_method},
456 
457  /*
458  * qo_set_cost
459  *
460  * This function is exported by optimizer/query_planner.c, and provides a backdoor that
461  * allows us some gross manipulation capabilities for the query
462  * optimizer. By adding it to the list of method implementations that
463  * are statically linked we make it easy for us to add a method to an
464  * arbitrary class for those cases where we need to poke the optimizer.
465  * To use this, try
466  *
467  * alter class foo add method class set_cost(string, string)
468  * function qo_set_cost;
469  *
470  * and then utter
471  *
472  * call set_cost('iscan', '0') on class foo;
473  */
474  {"qo_set_cost", (METHOD_LINK_FUNCTION) qo_set_cost},
475  {"get_attribute_number", (METHOD_LINK_FUNCTION) get_attribute_number},
476  {"dbmeth_class_name", (METHOD_LINK_FUNCTION) dbmeth_class_name},
477  {"dbmeth_print", (METHOD_LINK_FUNCTION) dbmeth_print},
478  {"au_change_sp_owner_method", (METHOD_LINK_FUNCTION) au_change_sp_owner_method},
479  {"au_change_serial_owner_method", (METHOD_LINK_FUNCTION) au_change_serial_owner_method},
480 
481  {NULL, NULL}
482 };
483 
484 
485 static int au_get_set (MOP obj, const char *attname, DB_SET ** set);
486 static int au_get_object (MOP obj, const char *attname, MOP * mop_ptr);
487 static int au_set_get_obj (DB_SET * set, int index, MOP * obj);
488 static AU_CLASS_CACHE *au_make_class_cache (int depth);
489 static void au_free_class_cache (AU_CLASS_CACHE * cache);
491 
492 static int au_extend_class_caches (int *index);
493 static int au_find_user_cache_index (DB_OBJECT * user, int *index, int check_it);
494 static void free_user_cache (AU_USER_CACHE * u);
495 static void reset_cache_for_user_and_class (SM_CLASS * sm_class);
496 
497 static void remove_user_cache_references (MOP user);
498 static void init_caches (void);
499 static void flush_caches (void);
500 
501 static MOP au_make_user (const char *name);
502 static int au_set_new_auth (MOP au_obj, MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, bool grant_option);
503 static MOP au_get_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type);
504 static int au_insert_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, int grant_option);
505 static int au_update_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, int grant_option);
506 static int au_delete_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type);
507 static int au_propagate_del_new_auth (AU_GRANT * glist, DB_AUTH mask);
508 
509 static int check_user_name (const char *name);
510 static void encrypt_password (const char *pass, int add_prefix, char *dest);
511 static void encrypt_password_sha1 (const char *pass, int add_prefix, char *dest);
512 static void encrypt_password_sha2_512 (const char *pass, char *dest);
513 static bool match_password (const char *user, const char *database);
514 static int au_set_password_internal (MOP user, const char *password, int encode, char encrypt_prefix);
515 
516 static int au_add_direct_groups (DB_SET * new_groups, DB_VALUE * value);
517 static int au_compute_groups (MOP member, const char *name);
518 static int au_add_member_internal (MOP group, MOP member, int new_user);
519 
520 static int find_grant_entry (DB_SET * grants, MOP class_mop, MOP grantor);
521 static int add_grant_entry (DB_SET * grants, MOP class_mop, MOP grantor);
522 static void drop_grant_entry (DB_SET * grants, int index);
523 static int get_grants (MOP auth, DB_SET ** grant_ptr, int filter);
524 static int apply_grants (MOP auth, MOP class_mop, unsigned int *bits);
525 static int update_cache (MOP classop, SM_CLASS * sm_class, AU_CLASS_CACHE * cache);
526 static int appropriate_error (unsigned int bits, unsigned int requested);
527 static int check_grant_option (MOP classop, SM_CLASS * sm_class, DB_AUTH type);
528 
529 static void free_grant_list (AU_GRANT * grants);
530 static int collect_class_grants (MOP class_mop, DB_AUTH type, MOP revoked_auth, int revoked_grant_index,
531  AU_GRANT ** return_grants);
532 static void map_grant_list (AU_GRANT * grants, MOP grantor);
533 static int propagate_revoke (AU_GRANT * grant_list, MOP owner, DB_AUTH mask);
534 
535 static int is_protected_class (MOP classmop, SM_CLASS * sm_class, DB_AUTH auth);
536 static int check_authorization (MOP classobj, SM_CLASS * sm_class, DB_AUTH type);
537 static int fetch_class (MOP op, MOP * return_mop, SM_CLASS ** return_class, AU_FETCHMODE fetchmode, FETCH_BY fetch_by);
538 static int au_fetch_class_internal (MOP op, SM_CLASS ** class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type,
540 
541 static int fetch_instance (MOP op, MOBJ * obj_ptr, AU_FETCHMODE fetchmode,
542  LC_FETCH_VERSION_TYPE read_fetch_version_type);
543 static int au_perform_login (const char *name, const char *password, bool ignore_dba_privilege);
544 
545 static CLASS_GRANT *make_class_grant (CLASS_USER * user, int cache);
546 static CLASS_USER *make_class_user (MOP user_obj);
547 static void free_class_grants (CLASS_GRANT * grants);
548 static void free_class_users (CLASS_USER * users);
549 static CLASS_USER *find_or_add_user (CLASS_AUTH * auth, MOP user_obj);
550 static int add_class_grant (CLASS_AUTH * auth, MOP source, MOP user, int cache);
551 static int build_class_grant_list (CLASS_AUTH * cl_auth, MOP class_mop);
552 static void issue_grant_statement (print_output & output_ctx, CLASS_AUTH * auth, CLASS_GRANT * grant, int authbits);
553 static int class_grant_loop (print_output & output_ctx, CLASS_AUTH * auth);
554 
555 static void au_print_cache (int cache, FILE * fp);
556 static void au_print_grant_entry (DB_SET * grants, int grant_index, FILE * fp);
557 static void au_print_auth (MOP auth, FILE * fp);
558 
559 static int au_change_serial_owner (MOP * object, MOP new_owner);
560 /*
561  * DB_ EXTENSION FUNCTIONS
562  */
563 
564 
565 /*
566  * au_get_set
567  * return: error code
568  * obj(in):
569  * attname(in):
570  * set(in):
571  */
572 static int
573 au_get_set (MOP obj, const char *attname, DB_SET ** set)
574 {
575  int error = NO_ERROR;
576  DB_VALUE value;
577 
578  *set = NULL;
579  error = obj_get (obj, attname, &value);
580  if (error == NO_ERROR)
581  {
582  if (!TP_IS_SET_TYPE (DB_VALUE_TYPE (&value)))
583  {
584  error = ER_OBJ_DOMAIN_CONFLICT;
585  }
586  else
587  {
588  if (DB_IS_NULL (&value))
589  {
590  *set = NULL;
591  }
592  else
593  {
594  *set = db_get_set (&value);
595  }
596 
597  /*
598  * since we almost ALWAYS end up iterating through the sets fetching
599  * objects, do a vector fetch immediately to avoid
600  * multiple server calls.
601  * Should have a sub db_ function for doing this.
602  */
603  if (*set != NULL)
604  {
605  error = db_fetch_set (*set, DB_FETCH_READ, 0);
606  if (error == NO_ERROR)
607  {
608  error = set_filter (*set);
609  }
610  /*
611  * shoudl be detecting the filtered elements and marking the
612  * object dirty if possible
613  */
614  }
615  }
616  }
617  return (error);
618 }
619 
620 /*
621  * au_get_object
622  * return: error code
623  * obj(in):
624  * attname(in):
625  * mop_ptr(in):
626  */
627 static int
628 au_get_object (MOP obj, const char *attname, MOP * mop_ptr)
629 {
630  int error = NO_ERROR;
631  DB_VALUE value;
632 
633  *mop_ptr = NULL;
634  error = obj_get (obj, attname, &value);
635  if (error == NO_ERROR)
636  {
637  if (DB_VALUE_TYPE (&value) != DB_TYPE_OBJECT)
638  {
639  error = ER_OBJ_DOMAIN_CONFLICT;
640  }
641  else
642  {
643  if (DB_IS_NULL (&value))
644  {
645  *mop_ptr = NULL;
646  }
647  else
648  {
649  *mop_ptr = db_get_object (&value);
650  }
651  }
652  }
653  return (error);
654 }
655 
656 /*
657  * au_set_get_obj -
658  * return: error code
659  * set(in):
660  * index(in):
661  * obj(out):
662  */
663 static int
664 au_set_get_obj (DB_SET * set, int index, MOP * obj)
665 {
666  int error = NO_ERROR;
667  DB_VALUE value;
668 
669  *obj = NULL;
670 
671  error = set_get_element (set, index, &value);
672  if (error == NO_ERROR)
673  {
674  if (DB_VALUE_TYPE (&value) != DB_TYPE_OBJECT)
675  {
676  error = ER_OBJ_DOMAIN_CONFLICT;
677  }
678  else
679  {
680  if (DB_IS_NULL (&value))
681  {
682  *obj = NULL;
683  }
684  else
685  {
686  *obj = db_get_object (&value);
687  }
688  }
689  }
690 
691  return error;
692 }
693 
694 
695 /*
696  * AUTHORIZATION CACHES
697  */
698 
699 /*
700  * au_make_class_cache - Allocates and initializes a new class cache
701  * return: new cache structure
702  * depth(in): number of elements to include in the cache
703  */
704 static AU_CLASS_CACHE *
706 {
707  AU_CLASS_CACHE *new_class_cache = NULL;
708  int i;
709  size_t size;
710 
711  if (depth <= 0)
712  {
714  }
715  else
716  {
717  size = sizeof (AU_CLASS_CACHE) + ((depth - 1) * sizeof (unsigned int));
718  new_class_cache = (AU_CLASS_CACHE *) malloc (size);
719  if (new_class_cache == NULL)
720  {
722  return NULL;
723  }
724 
725  new_class_cache->next = NULL;
726  new_class_cache->class_ = NULL;
727  for (i = 0; i < depth; i++)
728  {
729  new_class_cache->data[i] = AU_CACHE_INVALID;
730  }
731  }
732 
733  return new_class_cache;
734 }
735 
736 /*
737  * au_free_class_cache - Frees a class cache
738  * return: none
739  * cache(in): cache to free
740  */
741 static void
743 {
744  if (cache != NULL)
745  {
746  free_and_init (cache);
747  }
748 }
749 
750 /*
751  * au_install_class_cache - This allocates a new class cache and attaches
752  * it to a class.
753  * return: new class cache
754  * class(in): class structure to get the new cache
755  *
756  * Note: Once a cache/class association has been made, we also put the
757  * cache on the global cache list so we can maintain it consistently.
758  */
759 static AU_CLASS_CACHE *
761 {
762  AU_CLASS_CACHE *new_class_cache;
763 
764  new_class_cache = au_make_class_cache (Au_cache_max);
765  if (new_class_cache != NULL)
766  {
767  new_class_cache->next = Au_class_caches;
768  Au_class_caches = new_class_cache;
769  new_class_cache->class_ = sm_class;
770  sm_class->auth_cache = new_class_cache;
771  }
772 
773  return new_class_cache;
774 }
775 
776 /*
777  * au_free_authorization_cache - This removes a class cache from the global
778  * cache list, detaches it from the class
779  * and frees it.
780  * return: none
781  * cache(in): class cache
782  */
783 void
785 {
786  AU_CLASS_CACHE *c, *prev;
787 
788  if (cache != NULL)
789  {
790  for (c = Au_class_caches, prev = NULL; c != NULL && c != cache; c = c->next)
791  {
792  prev = c;
793  }
794  if (c != NULL)
795  {
796  if (prev == NULL)
797  {
798  Au_class_caches = c->next;
799  }
800  else
801  {
802  prev->next = c->next;
803  }
804  }
806  }
807 }
808 
809 /*
810  * au_extend_class_caches - This extends the all existing class caches so they
811  * can contain an additional element.
812  * return: error code
813  * index(out): next available index
814  *
815  * Note: If we have already preallocated some extra elements it will use one
816  * and avoid reallocating all the caches. If we have no extra elements,
817  * we grow all the caches by a certain amount.
818  */
819 static int
821 {
822  int error = NO_ERROR;
823  AU_CLASS_CACHE *c, *new_list, *new_entry, *next;
824  int new_max, i;
825 
827  {
828  *index = Au_cache_depth;
829  Au_cache_depth++;
830  }
831  else
832  {
833  new_list = NULL;
834  new_max = Au_cache_max + Au_cache_increment;
835 
836  for (c = Au_class_caches; c != NULL && !error; c = c->next)
837  {
838  new_entry = au_make_class_cache (new_max);
839  if (new_entry == NULL)
840  {
841  assert (er_errid () != NO_ERROR);
842  error = er_errid ();
843  }
844  else
845  {
846  for (i = 0; i < Au_cache_depth; i++)
847  {
848  new_entry->data[i] = c->data[i];
849  }
850  new_entry->class_ = c->class_;
851  new_entry->next = new_list;
852  new_list = new_entry;
853  }
854  }
855 
856  if (!error)
857  {
858  for (c = Au_class_caches, next = NULL; c != NULL; c = next)
859  {
860  next = c->next;
861  c->class_->auth_cache = NULL;
863  }
864  for (c = new_list; c != NULL; c = c->next)
865  {
866  c->class_->auth_cache = c;
867  }
868 
869  Au_class_caches = new_list;
870  Au_cache_max = new_max;
871  *index = Au_cache_depth;
872  Au_cache_depth++;
873  }
874  }
875 
876  return error;
877 }
878 
879 /*
880  * au_find_user_cache_index - This determines the cache index for the given
881  * user.
882  * return: error code
883  * user(in): user object
884  * index(out): returned user index
885  * check_it(in):
886  *
887  * Note: If the user has never been added to the authorization cache,
888  * we reserve a new index for the user. Reserving the user index may
889  * result in growing all the existing class caches.
890  * This is the primary work function for AU_SET_USER() and it should
891  * be fast.
892  */
893 static int
894 au_find_user_cache_index (DB_OBJECT * user, int *index, int check_it)
895 {
896  int error = NO_ERROR;
897  AU_USER_CACHE *u, *new_user_cache;
898  DB_OBJECT *class_mop;
899 
900  for (u = Au_user_cache; u != NULL && !ws_is_same_object (u->user, user); u = u->next)
901  ;
902 
903  if (u != NULL)
904  {
905  *index = u->index;
906  }
907  else
908  {
909  /*
910  * User wasn't in the cache, add it and extend the existing class
911  * caches. First do a little sanity check just to make sure this
912  * is a user object.
913  */
914  if (check_it)
915  {
916  class_mop = sm_get_class (user);
917  if (class_mop == NULL)
918  {
919  assert (er_errid () != NO_ERROR);
920  return er_errid ();
921  }
922  else if (class_mop != Au_user_class)
923  {
924  error = ER_AU_CORRUPTED; /* need a better error */
926  return er_errid ();
927  }
928  }
929 
930  new_user_cache = (AU_USER_CACHE *) malloc (sizeof (AU_USER_CACHE));
931  if (new_user_cache != NULL)
932  {
933  if ((error = au_extend_class_caches (index)))
934  {
935  free_and_init (new_user_cache);
936  }
937  else
938  {
939  new_user_cache->next = Au_user_cache;
940  Au_user_cache = new_user_cache;
941  new_user_cache->user = user;
942  new_user_cache->index = *index;
943  }
944  }
945  }
946 
947  return error;
948 }
949 
950 /*
951  * free_user_cache - Frees a user cache. Make sure to clear the MOP pointer.
952  * returns: none
953  * u(in): user cache
954  */
955 static void
957 {
958  if (u != NULL)
959  {
960  u->user = NULL; /* clear GC roots */
961  free_and_init (u);
962  }
963 }
964 
965 
966 /*
967  * reset_cache_for_user_and_class - This is called whenever a grant or revoke
968  * operation is performed. It resets the
969  * caches only for a particular
970  * user/class pair
971  * return : none
972  * class(in): class structure
973  *
974  * Note: This was originally written so that only the authorization
975  * cache for the given user was cleared. This does not work however
976  * if we're changing authorization for a group and there are members
977  * of that group already cached.
978  * We could be smart and try to invalidate the caches of all
979  * members of this user but instead just go ahead and invalidate
980  * everyone's cache for this class. This isn't optimal but doesn't really
981  * matter that much. grant/revoke don't happen very often.
982  */
983 static void
985 {
986  AU_USER_CACHE *u;
987  AU_CLASS_CACHE *c;
988 
989  for (c = Au_class_caches; c != NULL && c->class_ != sm_class; c = c->next);
990  if (c != NULL)
991  {
992  /*
993  * invalide every user's cache for this class_, could be more
994  * selective and do only the given user and its members
995  */
996  for (u = Au_user_cache; u != NULL; u = u->next)
997  {
998  c->data[u->index] = AU_CACHE_INVALID;
999  }
1000  }
1001 }
1002 
1003 /*
1004  * au_reset_authorization_caches - This is called by ws_clear_all_hints()
1005  * and ws_abort_mops() on transaction
1006  * boundaries.
1007  * return: none
1008  *
1009  * Note: We reset all the authorization caches at this point.
1010  * This sets all of the authorization entries in a cache to be invalid.
1011  * Normally this is done when the authorization for this
1012  * class changes in some way. The next time the cache is used, it
1013  * will force the recomputation of the authorization bits.
1014  * We should try to be smarter and flush the caches only when we know
1015  * that the authorization catalogs have changed in some way.
1016  */
1017 
1018 void
1020 {
1021  AU_CLASS_CACHE *c;
1022  int i;
1023 
1024  for (c = Au_class_caches; c != NULL; c = c->next)
1025  {
1026  for (i = 0; i < Au_cache_depth; i++)
1027  {
1028  c->data[i] = AU_CACHE_INVALID;
1029  }
1030  }
1031 }
1032 
1033 /*
1034  * remove_user_cache_reference - This is called when a user object is deleted.
1035  * return: none
1036  * user(in): user object
1037  *
1038  * Note: If there is an authorization cache entry for this user, we NULL
1039  * the user pointer so it will no longer be used. We could to in
1040  * and restructure all the caches to remove the deleted user but user
1041  * deletion isn't that common. Just leave an unused entry in the
1042  * cache array.
1043  */
1044 static void
1046 {
1047  AU_USER_CACHE *u;
1048 
1049  for (u = Au_user_cache; u != NULL; u = u->next)
1050  {
1051  if (ws_is_same_object (u->user, user))
1052  {
1053  u->user = NULL;
1054  }
1055  }
1056 }
1057 
1058 /*
1059  * init_caches - Called during au_init(). Initialize all of the cache
1060  * related global variables.
1061  * return: none
1062  */
1063 static void
1065 {
1066  Au_user_cache = NULL;
1067  Au_class_caches = NULL;
1068  Au_cache_depth = 0;
1069  Au_cache_max = 0;
1070  Au_cache_increment = 4;
1071  Au_cache_index = -1;
1072 }
1073 
1074 /*
1075  * flush_caches - Called during au_final(). Free the authorization cache
1076  * structures and initialize the global variables
1077  * to their default state.
1078  * return : none
1079  */
1080 static void
1082 {
1083  AU_USER_CACHE *u, *nextu;
1084  AU_CLASS_CACHE *c, *nextc;
1085 
1086  for (c = Au_class_caches, nextc = NULL; c != NULL; c = nextc)
1087  {
1088  nextc = c->next;
1089  c->class_->auth_cache = NULL;
1090  au_free_class_cache (c);
1091  }
1092  for (u = Au_user_cache, nextu = NULL; u != NULL; u = nextu)
1093  {
1094  nextu = u->next;
1095  free_user_cache (u);
1096  }
1097 
1098  /* clear the associated globals */
1099  init_caches ();
1100 }
1101 
1102 
1103 /*
1104  * COMPARISON
1105  */
1106 
1107 #if defined(ENABLE_UNUSED_FUNCTION)
1108 /*
1109  * toupper_string - This is used to add a user or compare two user names.
1110  * return: convert a string to upper case
1111  * name1: user name
1112  * name2: user name
1113  *
1114  * Note: User names are stored in upper case.
1115  * This is split into a separate function in case we need to make
1116  * modifications to this for Internationalization.
1117  */
1118 char *
1119 toupper_string (const char *name1, char *name2)
1120 {
1121  char *buffer, *ptr;
1122 
1123  buffer = (char *) malloc (strlen (name1) * 2 + 1);
1124  if (buffer == NULL)
1125  {
1126  return NULL;
1127  }
1128 
1129  intl_mbs_upper (name1, buffer);
1130  ptr = buffer;
1131  while (*ptr != '\0')
1132  {
1133  *name2++ = *ptr++;
1134  }
1135  *name2 = '\0';
1136 
1137  free (buffer);
1138  return name2;
1139 }
1140 #endif
1141 
1142 /*
1143  * USER/GROUP ACCESS
1144  */
1145 
1146 /*
1147  * au_find_user - Find a user object by name.
1148  * return: user object
1149  * user_name(in): name
1150  *
1151  * Note: The db_root class used to have a users attribute which was a set
1152  * containing the object-id for all users.
1153  * The users attribute has been eliminated for performance reasons.
1154  * A query is now used to find the user. Since the user name is not
1155  * case insensitive, it is set to upper case in the query. This forces
1156  * user names to be set to upper case when users are added.
1157  */
1158 MOP
1159 au_find_user (const char *user_name)
1160 {
1161  MOP obj, user = NULL;
1162  int save;
1163  char *query;
1164  DB_QUERY_RESULT *query_result;
1165  DB_QUERY_ERROR query_error;
1166  int error = NO_ERROR;
1167  DB_VALUE user_val;
1168  const char *qp1 = "select [%s] from [%s] where [name] = '%s' using index none";
1169  MOP user_class;
1170  char *upper_case_name;
1171  size_t upper_case_name_size;
1172  DB_VALUE user_name_string;
1173 
1174  if (user_name == NULL)
1175  {
1176  return NULL;
1177  }
1178 
1179  /* disable checking of internal authorization object access */
1180  AU_DISABLE (save);
1181 
1182  user = NULL;
1183 
1184  upper_case_name_size = intl_identifier_upper_string_size (user_name);
1185  upper_case_name = (char *) malloc (upper_case_name_size + 1);
1186  if (upper_case_name == NULL)
1187  {
1188  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, upper_case_name_size);
1189  return NULL;
1190  }
1191  intl_identifier_upper (user_name, upper_case_name);
1192 
1193  /*
1194  * first try to find the user id by index. This is faster than
1195  * a query, and will not get blocked out as a server request
1196  * if the query processing resources are all used up at the moment.
1197  * This is primarily of importance during logging in.
1198  */
1199  user_class = db_find_class ("db_user");
1200  if (user_class)
1201  {
1202  db_make_string (&user_name_string, upper_case_name);
1203  user = obj_find_unique (user_class, "name", &user_name_string, AU_FETCH_READ);
1204  }
1205  error = er_errid ();
1206 
1207  if (error != NO_ERROR)
1208  {
1209  if (error == ER_OBJ_OBJECT_NOT_FOUND)
1210  {
1212  }
1213  goto exit;
1214  }
1215 
1216  if (error == NO_ERROR && !user)
1217  {
1218  /* proceed with the query version of the function */
1219  query = (char *) malloc (strlen (qp1) + (2 * strlen (AU_USER_CLASS_NAME)) + strlen (upper_case_name) + 1);
1220  if (query)
1221  {
1222  sprintf (query, qp1, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME, upper_case_name);
1223 
1225  error = db_compile_and_execute_local (query, &query_result, &query_error);
1227  /* error is row count if not negative. */
1228  if (error > 0)
1229  {
1230  if (db_query_first_tuple (query_result) == DB_CURSOR_SUCCESS)
1231  {
1232  if (db_query_get_tuple_value (query_result, 0, &user_val) == NO_ERROR)
1233  {
1234  if (DB_IS_NULL (&user_val))
1235  {
1236  obj = NULL;
1237  }
1238  else
1239  {
1240  obj = db_get_object (&user_val);
1241  }
1242  if (obj)
1243  {
1244  user = obj;
1245  }
1246  }
1247  }
1248  }
1249  if (error >= 0)
1250  {
1251  db_query_end (query_result);
1252  }
1253  free_and_init (query);
1254  }
1255  }
1256 
1257 exit:
1258  AU_ENABLE (save);
1259 
1260  if (upper_case_name)
1261  {
1262  free_and_init (upper_case_name);
1263  }
1264  return (user);
1265 }
1266 
1267 /*
1268  * au_find_user_to_drop - Find a user object by name for dropping.
1269  *
1270  * return: error code
1271  * user_name(in): name
1272  * user(out): user object
1273  *
1274  * Note: X_Lock will be added on this user_object
1275  We also need check whether ths user is an active user.
1276  */
1277 int
1278 au_find_user_to_drop (const char *user_name, MOP * user)
1279 {
1280  int error = NO_ERROR;
1281  bool existed;
1282  MOP user_class;
1283  char *upper_case_name = NULL;
1284  size_t upper_case_name_size;
1285  DB_VALUE user_name_string;
1286 
1287  *user = NULL;
1288 
1289  /* check current user is DBA group */
1290  if (Au_dba_user != NULL && !au_is_dba_group_member (Au_user))
1291  {
1292  error = ER_AU_DBA_ONLY;
1293  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "drop_user");
1294  goto exit;
1295  }
1296 
1297  upper_case_name_size = intl_identifier_upper_string_size (user_name);
1298  upper_case_name = (char *) malloc (upper_case_name_size + 1);
1299  if (upper_case_name == NULL)
1300  {
1301  error = ER_OUT_OF_VIRTUAL_MEMORY;
1302  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, upper_case_name_size);
1303  goto exit;
1304  }
1305  intl_identifier_upper (user_name, upper_case_name);
1306 
1307  /* find the user object */
1308  user_class = db_find_class (AU_USER_CLASS_NAME);
1309  if (user_class == NULL)
1310  {
1311  error = er_errid ();
1312  assert (error != NO_ERROR);
1313  goto exit;
1314  }
1315 
1316  db_make_string (&user_name_string, upper_case_name);
1317  *user = obj_find_unique (user_class, "name", &user_name_string, AU_FETCH_WRITE);
1318  if ((*user) == NULL)
1319  {
1320  error = er_errid ();
1321  assert (error != NO_ERROR);
1322  if (error == ER_OBJ_OBJECT_NOT_FOUND)
1323  {
1324  error = ER_AU_INVALID_USER;
1325  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, user_name);
1326  }
1327  goto exit;
1328  }
1329 
1330  /* check whether this user is an active user */
1331  error = log_does_active_user_exist (upper_case_name, &existed);
1332  if (error == NO_ERROR && existed)
1333  {
1335  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, user_name);
1336  }
1337 
1338 exit:
1339 
1340  if (upper_case_name)
1341  {
1342  free_and_init (upper_case_name);
1343  }
1344 
1345  if (error != NO_ERROR)
1346  {
1347  *user = NULL;
1348  }
1349 
1350  return error;
1351 }
1352 
1353 /*
1354  * au_find_user_method - Method interface to au_find_user.
1355  * return: none
1356  * class(in):
1357  * returnval(out):
1358  * name(in):
1359  */
1360 void
1361 au_find_user_method (MOP class_mop, DB_VALUE * returnval, DB_VALUE * name)
1362 {
1363  MOP user;
1364  int error = NO_ERROR;
1365 
1366  db_make_null (returnval);
1367  if (name != NULL && IS_STRING (name) && !DB_IS_NULL (name) && db_get_string (name) != NULL)
1368  {
1369  user = au_find_user (db_get_string (name));
1370  if (user != NULL)
1371  {
1372  db_make_object (returnval, user);
1373  }
1374  }
1375  else
1376  {
1377  error = ER_AU_INVALID_USER;
1378  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
1379  db_make_error (returnval, error);
1380  }
1381 }
1382 
1383 /*
1384  * au_make_user - Create a new user object. Convert the name to upper case
1385  * so that au_find_user can use a query.
1386  * return: new user object
1387  * name(in): user name
1388  */
1389 static MOP
1390 au_make_user (const char *name)
1391 {
1392  MOP uclass, aclass, user, auth;
1393  DB_VALUE value;
1394  DB_SET *set;
1395  char *lname;
1396  int error;
1397 
1398  user = NULL;
1399  uclass = sm_find_class (AU_USER_CLASS_NAME);
1400  if (uclass == NULL)
1401  {
1403  }
1404  else
1405  {
1406  aclass = sm_find_class (AU_AUTH_CLASS_NAME);
1407  if (aclass == NULL)
1408  {
1410  }
1411  else
1412  {
1413  int name_size;
1414 
1415  user = obj_create (uclass);
1416  name_size = intl_identifier_upper_string_size (name);
1417  lname = (char *) malloc (name_size + 1);
1418  if (lname)
1419  {
1420  intl_identifier_upper (name, lname);
1421  db_make_string (&value, lname);
1422  error = obj_set (user, "name", &value);
1423  free_and_init (lname);
1424  if (error != NO_ERROR)
1425  {
1426  if (!ER_IS_ABORTED_DUE_TO_DEADLOCK (error))
1427  {
1429  obj_delete (user);
1430  }
1431  user = NULL;
1432  }
1433  else
1434  {
1435  /* flattened group list */
1436  set = set_create_basic ();
1437  if (set == NULL)
1438  {
1439  goto memory_error;
1440  }
1441  db_make_set (&value, set);
1442  obj_set (user, "groups", &value);
1443  set_free (set);
1444 
1445  /* direct group list */
1446  set = set_create_basic ();
1447  if (set == NULL)
1448  {
1449  goto memory_error;
1450  }
1451  db_make_set (&value, set);
1452  obj_set (user, "direct_groups", &value);
1453  set_free (set);
1454 
1455  /* authorization object */
1456  auth = obj_create (aclass);
1457  if (auth == NULL)
1458  {
1459  goto memory_error;
1460  }
1461  db_make_object (&value, user);
1462  /* back pointer to user object */
1463  obj_set (auth, "owner", &value);
1464  set = set_create_sequence (0);
1465  if (set == NULL)
1466  {
1467  goto memory_error;
1468  }
1469  db_make_sequence (&value, set);
1470  obj_set (auth, "grants", &value);
1471  set_free (set);
1472 
1473  db_make_object (&value, auth);
1474  obj_set (user, "authorization", &value);
1475 
1476  db_make_null (&value);
1477  obj_set (user, "comment", &value);
1478  }
1479  }
1480  else
1481  {
1482  goto memory_error;
1483  }
1484  }
1485  }
1486  return (user);
1487 
1488 memory_error:
1489  if (user != NULL)
1490  {
1491  obj_delete (user);
1492  }
1493  return NULL;
1494 }
1495 
1496 /*
1497  * au_set_new_auth -
1498  * return: error code
1499  * au_obj(in):
1500  * grantor(in):
1501  * user(in):
1502  * class(in):
1503  * auth_type(in):
1504  * grant_option(in):
1505  */
1506 static int
1507 au_set_new_auth (MOP au_obj, MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, bool grant_option)
1508 {
1509  int error = NO_ERROR;
1510  MOP au_class, db_class = NULL, db_class_inst = NULL;
1511  DB_VALUE value, class_name_val;
1512  DB_AUTH type;
1513  int i;
1514  const char *type_set[] = { "SELECT", "INSERT", "UPDATE", "DELETE", "ALTER", "INDEX", "EXECUTE" };
1515 
1516  if (au_obj == NULL)
1517  {
1518  au_class = sm_find_class (CT_CLASSAUTH_NAME);
1519  if (au_class == NULL)
1520  {
1521  error = ER_AU_MISSING_CLASS;
1523  return error;
1524  }
1525  au_obj = db_create_internal (au_class);
1526  if (au_obj == NULL)
1527  {
1528  assert (er_errid () != NO_ERROR);
1529  return er_errid ();
1530  }
1531  }
1532 
1533  db_make_object (&value, grantor);
1534  obj_set (au_obj, "grantor", &value);
1535 
1536  db_make_object (&value, user);
1537  obj_set (au_obj, "grantee", &value);
1538 
1539  db_class = sm_find_class (CT_CLASS_NAME);
1540  if (db_class == NULL)
1541  {
1542  assert (er_errid () != NO_ERROR);
1543  return er_errid ();
1544  }
1545 
1546  db_make_string (&class_name_val, sm_get_ch_name (class_mop));
1547  db_class_inst = obj_find_unique (db_class, "class_name", &class_name_val, AU_FETCH_READ);
1548  if (db_class_inst == NULL)
1549  {
1550  assert (er_errid () != NO_ERROR);
1551  pr_clear_value (&class_name_val);
1552  return er_errid ();
1553  }
1554 
1555  db_make_object (&value, db_class_inst);
1556  obj_set (au_obj, "class_of", &value);
1557 
1558  for (type = DB_AUTH_SELECT, i = 0; type != auth_type; type = (DB_AUTH) (type << 1), i++)
1559  {
1560  ;
1561  }
1562 
1563  db_make_varchar (&value, 7, type_set[i], strlen (type_set[i]), LANG_SYS_CODESET, LANG_SYS_COLLATION);
1564  obj_set (au_obj, "auth_type", &value);
1565 
1566  db_make_int (&value, (int) grant_option);
1567  obj_set (au_obj, "is_grantable", &value);
1568 
1569  pr_clear_value (&class_name_val);
1570  return NO_ERROR;
1571 }
1572 
1573 /*
1574  * au_get_new_auth -
1575  * return:
1576  * grantor(in):
1577  * user(in):
1578  * class_mop(in):
1579  * auth_type(in):
1580  */
1581 static MOP
1582 au_get_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type)
1583 {
1584  int error = NO_ERROR, save, i;
1585  DB_AUTH type;
1586  MOP ret_obj = NULL;
1587  const char *class_name;
1588  const char *sql_query =
1589  "SELECT [au].object FROM [" CT_CLASSAUTH_NAME "] [au]"
1590  " WHERE [au].[grantee].[name] = ? AND [au].[grantor].[name] = ?"
1591  " AND [au].[class_of].[class_name] = ? AND [au].[auth_type] = ?";
1592  enum
1593  {
1594  INDEX_FOR_GRANTEE_NAME = 0,
1595  INDEX_FOR_GRANTOR_NAME = 1,
1596  INDEX_FOR_CLASS_NAME = 2,
1597  INDEX_FOR_AUTH_TYPE = 3,
1598  /* Total count for the above */
1599  COUNT_FOR_VARIABLES
1600  };
1601  DB_VALUE val[COUNT_FOR_VARIABLES];
1602  DB_VALUE grant_value;
1603  DB_QUERY_RESULT *result = NULL;
1604  DB_SESSION *session = NULL;
1605  STATEMENT_ID stmt_id;
1606  const char *type_set[] = { "SELECT", "INSERT", "UPDATE", "DELETE", "ALTER", "INDEX", "EXECUTE" };
1607 
1608  for (i = 0; i < COUNT_FOR_VARIABLES; i++)
1609  {
1610  db_make_null (&val[i]);
1611  }
1612 
1613  db_make_null (&grant_value);
1614 
1615  /* Disable the checking for internal authorization object access */
1616  AU_DISABLE (save);
1617 
1618  /* Prepare DB_VALUEs for host variables */
1619  error = obj_get (user, "name", &val[INDEX_FOR_GRANTEE_NAME]);
1620  if (error != NO_ERROR)
1621  {
1622  goto exit;
1623  }
1624  else if (!IS_STRING (&val[INDEX_FOR_GRANTEE_NAME]) || DB_IS_NULL (&val[INDEX_FOR_GRANTEE_NAME])
1625  || db_get_string (&val[INDEX_FOR_GRANTEE_NAME]) == NULL)
1626  {
1628  goto exit;
1629  }
1630 
1631  error = obj_get (grantor, "name", &val[INDEX_FOR_GRANTOR_NAME]);
1632  if (error != NO_ERROR)
1633  {
1634  goto exit;
1635  }
1636  else if (!IS_STRING (&val[INDEX_FOR_GRANTOR_NAME]) || DB_IS_NULL (&val[INDEX_FOR_GRANTOR_NAME])
1637  || db_get_string (&val[INDEX_FOR_GRANTOR_NAME]) == NULL)
1638  {
1640  goto exit;
1641  }
1642 
1643  class_name = db_get_class_name (class_mop);
1644  if (class_name == NULL)
1645  {
1647  goto exit;
1648  }
1649  db_make_string (&val[INDEX_FOR_CLASS_NAME], class_name);
1650 
1651  for (type = DB_AUTH_SELECT, i = 0; type != auth_type; type = (DB_AUTH) (type << 1), i++)
1652  {
1653  ;
1654  }
1655  db_make_string (&val[INDEX_FOR_AUTH_TYPE], type_set[i]);
1656 
1657  session = db_open_buffer (sql_query);
1658  if (session == NULL)
1659  {
1660  assert (er_errid () != NO_ERROR);
1661  goto release;
1662  }
1663 
1664  error = db_push_values (session, COUNT_FOR_VARIABLES, val);
1665  if (error != NO_ERROR)
1666  {
1667  assert (er_errid () != NO_ERROR);
1668  goto release;
1669  }
1670 
1671  stmt_id = db_compile_statement (session);
1672  if (stmt_id != 1)
1673  {
1674  assert (er_errid () != NO_ERROR);
1675  goto release;
1676  }
1677 
1678  error = db_execute_statement_local (session, stmt_id, &result);
1679 
1680  /* The error value is row count if it's not negative value. */
1681  if (error == 0)
1682  {
1684  goto release;
1685  }
1686  else if (error < 0)
1687  {
1688  assert (er_errid () != NO_ERROR);
1689  goto release;
1690  }
1691 
1692  error = NO_ERROR;
1693 
1694  if (db_query_first_tuple (result) == DB_CURSOR_SUCCESS)
1695  {
1696  if (db_query_get_tuple_value (result, 0, &grant_value) == NO_ERROR)
1697  {
1698  ret_obj = NULL;
1699  if (!DB_IS_NULL (&grant_value))
1700  {
1701  ret_obj = db_get_object (&grant_value);
1702  }
1703  }
1704 
1706  }
1707 
1708  assert (ret_obj != NULL);
1709 
1710 release:
1711  if (result != NULL)
1712  {
1713  db_query_end (result);
1714  }
1715  if (session != NULL)
1716  {
1717  db_close_session (session);
1718  }
1719 
1720 exit:
1721  AU_ENABLE (save);
1722 
1723  db_value_clear (&grant_value);
1724 
1725  for (i = 0; i < COUNT_FOR_VARIABLES; i++)
1726  {
1727  db_value_clear (&val[i]);
1728  }
1729 
1730  if (ret_obj == NULL && er_errid () == NO_ERROR)
1731  {
1733  }
1734 
1735  return (ret_obj);
1736 }
1737 
1738 /*
1739  * au_insert_new_auth -
1740  * return: error code
1741  * grantor(in):
1742  * user(in):
1743  * class_mop(in):
1744  * auth_type(in):
1745  * grant_option(in):
1746  */
1747 static int
1748 au_insert_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, int grant_option)
1749 {
1750  int index;
1751  int error = NO_ERROR;
1752 
1753  for (index = DB_AUTH_EXECUTE; index; index >>= 1)
1754  {
1755  if (auth_type & index)
1756  {
1757  error =
1758  au_set_new_auth (NULL, grantor, user, class_mop, (DB_AUTH) index, ((grant_option & index) ? true : false));
1759  if (error != NO_ERROR)
1760  {
1761  break;
1762  }
1763  }
1764  }
1765 
1766  return error;
1767 }
1768 
1769 /*
1770  * au_update_new_auth -
1771  * return: error code
1772  * grantor(in):
1773  * user(in):
1774  * class_mop(in):
1775  * auth_type(in):
1776  * grant_option(in):
1777  */
1778 static int
1779 au_update_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, int grant_option)
1780 {
1781  MOP au_obj;
1782  int index;
1783  int error = NO_ERROR;
1784 
1785  for (index = DB_AUTH_EXECUTE; index; index >>= 1)
1786  {
1787  if (auth_type & index)
1788  {
1789  au_obj = au_get_new_auth (grantor, user, class_mop, (DB_AUTH) index);
1790  if (au_obj == NULL)
1791  {
1792  assert (er_errid () != NO_ERROR);
1793  return er_errid ();
1794  }
1795 
1796  error = obj_inst_lock (au_obj, 1);
1797  if (error != NO_ERROR)
1798  {
1799  return error;
1800  }
1801 
1802  error =
1803  au_set_new_auth (au_obj, grantor, user, class_mop, (DB_AUTH) index,
1804  ((grant_option & index) ? true : false));
1805  if (error != NO_ERROR)
1806  {
1807  return error;
1808  }
1809  }
1810  }
1811 
1812  return error;
1813 }
1814 
1815 /*
1816  * au_delete_new_auth -
1817  * return: error code
1818  * grantor(in):
1819  * user(in):
1820  * class_mop(in):
1821  * auth_type(in):
1822  */
1823 static int
1824 au_delete_new_auth (MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type)
1825 {
1826  MOP au_obj;
1827  int index;
1828  int error = NO_ERROR;
1829 
1830  for (index = DB_AUTH_EXECUTE; index; index >>= 1)
1831  {
1832  if (auth_type & index)
1833  {
1834  au_obj = au_get_new_auth (grantor, user, class_mop, (DB_AUTH) index);
1835  if (au_obj == NULL)
1836  {
1837  assert (er_errid () != NO_ERROR);
1838  return er_errid ();
1839  }
1840 
1841  error = obj_inst_lock (au_obj, 1);
1842  if (error != NO_ERROR)
1843  {
1844  return error;
1845  }
1846 
1847  error = obj_delete (au_obj);
1848  if (error != NO_ERROR)
1849  {
1850  return error;
1851  }
1852  }
1853  }
1854 
1855  return error;
1856 }
1857 
1858 /*
1859  * au_propagate_del_new_auth -
1860  * return: error code
1861  * glist(in):
1862  * mask(in):
1863  */
1864 static int
1866 {
1867  AU_GRANT *g;
1868  DB_SET *grants;
1869  DB_VALUE class_, type;
1870  int error = NO_ERROR;
1871 
1872  for (g = glist; g != NULL; g = g->next)
1873  {
1874  if (!g->legal)
1875  {
1876  error = get_grants (g->auth_object, &grants, 0);
1877  if (error != NO_ERROR)
1878  {
1879  break;
1880  }
1881 
1882  error = set_get_element (grants, GRANT_ENTRY_CLASS (g->grant_index), &class_);
1883  if (error != NO_ERROR)
1884  {
1885  break;
1886  }
1887 
1888  error = set_get_element (grants, GRANT_ENTRY_CACHE (g->grant_index), &type);
1889  if (error != NO_ERROR)
1890  {
1891  break;
1892  }
1893 
1894  error =
1895  au_delete_new_auth (g->grantor, g->user, db_get_object (&class_), (DB_AUTH) (db_get_int (&type) & ~mask));
1896  if (error != NO_ERROR)
1897  {
1898  break;
1899  }
1900  }
1901  }
1902 
1903  return error;
1904 }
1905 
1906 /*
1907  * au_force_write_new_auth -
1908  * return: error code
1909  */
1910 int
1912 {
1913  DB_OBJLIST *list, *mop;
1914  MOP au_class, au_obj;
1915  DB_VALUE grants_val;
1916  DB_SET *grants;
1917  DB_VALUE grantor_val, grantee_val, class_val, auth_val;
1918  MOP grantor, grantee, class_;
1919  DB_AUTH auth;
1920  int gindex, gsize;
1921  int save;
1922  int error = NO_ERROR;
1923 
1924  list = NULL;
1925 
1926  AU_DISABLE (save);
1927 
1928  au_class = sm_find_class (AU_AUTH_CLASS_NAME);
1929  if (au_class == NULL)
1930  {
1931  error = ER_AU_NO_AUTHORIZATION;
1932  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
1933  goto end;
1934  }
1935 
1937  if (list == NULL)
1938  {
1939  error = ER_AU_NO_AUTHORIZATION;
1940  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
1941  goto end;
1942  }
1943 
1944  for (mop = list; mop != NULL; mop = mop->next)
1945  {
1946  au_obj = mop->op;
1947 
1948  error = obj_get (au_obj, "owner", &grantee_val);
1949  if (error != NO_ERROR)
1950  {
1951  goto end;
1952  }
1953  grantee = db_get_object (&grantee_val);
1954 
1955  error = obj_get (au_obj, "grants", &grants_val);
1956  if (error != NO_ERROR)
1957  {
1958  goto end;
1959  }
1960  grants = db_get_set (&grants_val);
1961 
1962  gsize = set_size (grants);
1963  for (gindex = 0; gindex < gsize; gindex += GRANT_ENTRY_LENGTH)
1964  {
1965  error = set_get_element (grants, GRANT_ENTRY_CLASS (gindex), &class_val);
1966  if (error != NO_ERROR)
1967  {
1968  goto end;
1969  }
1970  class_ = db_get_object (&class_val);
1971 
1972  error = set_get_element (grants, GRANT_ENTRY_SOURCE (gindex), &grantor_val);
1973  if (error != NO_ERROR)
1974  {
1975  goto end;
1976  }
1977  grantor = db_get_object (&grantor_val);
1978 
1979  error = set_get_element (grants, GRANT_ENTRY_CACHE (gindex), &auth_val);
1980  if (error != NO_ERROR)
1981  {
1982  goto end;
1983  }
1984  auth = (DB_AUTH) db_get_int (&auth_val);
1985 
1986  error =
1987  au_insert_new_auth (grantor, grantee, class_, (DB_AUTH) (auth & AU_TYPE_MASK), (auth & AU_GRANT_MASK));
1988  if (error != NO_ERROR)
1989  {
1990  goto end;
1991  }
1992  }
1993  }
1994 
1995 end:
1996  if (list)
1997  {
1998  ml_ext_free (list);
1999  }
2000 
2001  AU_ENABLE (save);
2002 
2003  return error;
2004 }
2005 
2006 /*
2007  * au_delete_auth_of_dropping_table - delete _db_auth records refers to the given table.
2008  * return: error code
2009  * class_name(in): the class name to be dropped
2010  */
2011 int
2012 au_delete_auth_of_dropping_table (const char *class_name)
2013 {
2014  int error = NO_ERROR, save;
2015  const char *sql_query =
2016  "DELETE FROM [" CT_CLASSAUTH_NAME "] [au]" " WHERE [au].[class_of] IN" " (SELECT [cl] FROM " CT_CLASS_NAME
2017  " [cl] WHERE [class_name] = ?);";
2018  DB_VALUE val;
2019  DB_QUERY_RESULT *result = NULL;
2020  DB_SESSION *session = NULL;
2021  int stmt_id;
2022 
2023  db_make_null (&val);
2024 
2025  /* Disable the checking for internal authorization object access */
2026  AU_DISABLE (save);
2027 
2028  assert (class_name != NULL);
2029 
2030  session = db_open_buffer_local (sql_query);
2031  if (session == NULL)
2032  {
2033  ASSERT_ERROR_AND_SET (error);
2034  goto exit;
2035  }
2036 
2037  error = db_set_system_generated_statement (session);
2038  if (error != NO_ERROR)
2039  {
2040  goto release;
2041  }
2042 
2043  stmt_id = db_compile_statement_local (session);
2044  if (stmt_id < 0)
2045  {
2046  ASSERT_ERROR_AND_SET (error);
2047  goto release;
2048  }
2049 
2050  db_make_string (&val, class_name);
2051  error = db_push_values (session, 1, &val);
2052  if (error != NO_ERROR)
2053  {
2054  goto release;
2055  }
2056 
2057  error = db_execute_statement_local (session, stmt_id, &result);
2058  if (error < 0)
2059  {
2060  goto release;
2061  }
2062 
2063  error = db_query_end (result);
2064 
2065 release:
2066  if (session != NULL)
2067  {
2068  db_close_session (session);
2069  }
2070 
2071 exit:
2072  pr_clear_value (&val);
2073 
2074  AU_ENABLE (save);
2075 
2076  return error;
2077 }
2078 
2079 /*
2080  * check_user_name
2081  * return: error code
2082  * name(in): proposed user name
2083  *
2084  * Note: This is made void for ansi compatibility. It previously insured
2085  * that identifiers which were accepted could be parsed in the
2086  * language interface.
2087  *
2088  * ANSI allows any character in an identifier. It also allows reserved
2089  * words. In order to parse identifiers with non-alpha characters
2090  * or that are reserved words, an escape syntax is definned with double
2091  * quotes, "FROM", for example.
2092  */
2093 static int
2094 check_user_name (const char *name)
2095 {
2096  return NO_ERROR;
2097 }
2098 
2099 /*
2100  * au_is_dba_group_member - Determines if a given user is the DBA/a member
2101  * of the DBA group, or not
2102  * return: true or false
2103  * user(in): user object
2104  */
2105 bool
2107 {
2108  DB_SET *groups;
2109  DB_VALUE value;
2110  bool is_member = false;
2111  LC_FETCH_VERSION_TYPE read_fetch_instance_version;
2112 
2113  if (!user)
2114  {
2115  return false; /* avoid gratuitous er_set later */
2116  }
2117 
2118  if (ws_is_same_object (user, Au_dba_user))
2119  {
2120  return true;
2121  }
2122 
2123  /* Set fetch version type to read dirty version. */
2124  read_fetch_instance_version = TM_TRAN_READ_FETCH_VERSION ();
2126 
2127  if (au_get_set (user, "groups", &groups) == NO_ERROR)
2128  {
2129  db_make_object (&value, Au_dba_user);
2130  is_member = set_ismember (groups, &value);
2131  set_free (groups);
2132  }
2133 
2134  /* Restore fetch version type. */
2135  db_set_read_fetch_instance_version (read_fetch_instance_version);
2136 
2137  return is_member;
2138 }
2139 
2140 /*
2141  * au_add_user - Add a user object if one does not already exist.
2142  * return: new or existing user object
2143  * name(in): user name
2144  * exists(out): flag set if user already existed
2145  *
2146  * Note: If one already exists, return it and set the flag.
2147  * The db_root class used to have a user attribute which was a set
2148  * containing the object-id for all users. The users attribute has been
2149  * eliminated for performance reasons.
2150  *
2151  */
2152 MOP
2153 au_add_user (const char *name, int *exists)
2154 {
2155  MOP user;
2156  DB_VALUE value;
2157  int save;
2158 
2159  user = NULL;
2160  if (Au_dba_user != NULL && !au_is_dba_group_member (Au_user))
2161  {
2163  }
2164  else if (!check_user_name (name))
2165  {
2166  AU_DISABLE (save);
2167  user = NULL;
2168  if (exists != NULL)
2169  {
2170  *exists = 0;
2171  }
2172  if (name == NULL)
2173  {
2175  }
2176  else
2177  {
2178  user = au_find_user (name);
2179  if (user != NULL)
2180  {
2181  if (exists != NULL)
2182  {
2183  *exists = 1;
2184  }
2185  }
2186  else
2187  {
2188  if (er_errid () != ER_AU_INVALID_USER)
2189  {
2190  AU_ENABLE (save);
2191  return NULL;
2192  }
2193 
2194  /* clear error */
2195  er_clear ();
2196 
2197  user = au_make_user (name);
2198  if (user != NULL)
2199  {
2200  db_make_object (&value, user);
2201  if (Au_public_user != NULL)
2202  {
2203  /*
2204  * every user is a member of the PUBLIC group,
2205  * must make sure that the exported routines can't
2206  * be used to violate this internal connection
2207  */
2208  if (au_add_member_internal (Au_public_user, user, 1) != NO_ERROR)
2209  {
2211  }
2212  }
2213 
2214  /*
2215  * do we want to do this ?? - logically it is ok but this
2216  * means we can't have DBA members since this would
2217  * cause user hierarchy cycles.
2218  */
2219 #if 0
2220  if (Au_dba_user != NULL)
2221  {
2222  if (au_get_set (Au_dba_user, "groups", &dba_groups) == NO_ERROR)
2223  {
2224  db_make_object (&value, user);
2225  if (!set_ismember (dba_groups, &value))
2226  {
2227  db_set_add (dba_groups, &value);
2228  }
2229  set_free (dba_groups);
2230  }
2231  }
2232 #endif /* 0 */
2233  }
2234  }
2235  }
2236  AU_ENABLE (save);
2237  }
2238  return (user);
2239 }
2240 
2241 /*
2242  * au_add_user_method
2243  * return: none
2244  * class(in): class object
2245  * returnval(out): return value of this method
2246  * name(in):
2247  * password(in):
2248  */
2249 void
2250 au_add_user_method (MOP class_mop, DB_VALUE * returnval, DB_VALUE * name, DB_VALUE * password)
2251 {
2252  int error;
2253  int exists;
2254  MOP user;
2255  const char *tmp = NULL;
2256 
2257  if (name != NULL && IS_STRING (name) && !DB_IS_NULL (name) && ((tmp = db_get_string (name)) != NULL))
2258  {
2260  {
2261  error = ER_USER_NAME_TOO_LONG;
2262  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2263  db_make_error (returnval, error);
2264  return;
2265  }
2266  /*
2267  * although au_set_password will check this, check it out here before
2268  * we bother creating the user object
2269  */
2270  if (password != NULL && IS_STRING (password) && !DB_IS_NULL (password) && (tmp = db_get_string (password))
2271  && strlen (tmp) > AU_MAX_PASSWORD_CHARS)
2272  {
2273  error = ER_AU_PASSWORD_OVERFLOW;
2274  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2275  db_make_error (returnval, error);
2276  }
2277  else
2278  {
2279  user = au_add_user (db_get_string (name), &exists);
2280  if (user == NULL)
2281  {
2282  /* return the error that was set */
2283  db_make_error (returnval, er_errid ());
2284  }
2285  else if (exists)
2286  {
2287  error = ER_AU_USER_EXISTS;
2289  db_make_error (returnval, error);
2290  }
2291  else
2292  {
2293  if (password != NULL && IS_STRING (password) && !DB_IS_NULL (password))
2294  {
2295  error = au_set_password (user, db_get_string (password));
2296  if (error != NO_ERROR)
2297  {
2298  db_make_error (returnval, error);
2299  }
2300  else
2301  {
2302  db_make_object (returnval, user);
2303  }
2304  }
2305  else
2306  {
2307  db_make_object (returnval, user);
2308  }
2309  }
2310  }
2311  }
2312  else
2313  {
2314  error = ER_AU_INVALID_USER;
2315  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
2316  db_make_error (returnval, error);
2317  }
2318 }
2319 
2320 /*
2321  * Password Encoding
2322  */
2323 
2324 /*
2325  * Password encoding is a bit kludgey to support older databases where the
2326  * password was stored in an unencoded format. Since we don't want
2327  * to invalidate existing databases unless absolutely necessary, we
2328  * need a way to recognize if the password in the database is encoded or not.
2329  *
2330  * The kludge is to store encoded passwords with a special prefix character
2331  * that could not normally be typed as part of a password. This will
2332  * be the binary char \001 or Control-A. The prefix could be used
2333  * in the future to identify other encoding schemes in case we find
2334  * a better way to store passwords.
2335  *
2336  * If the password string has this prefix character, we can assume that it
2337  * has been encoded, otherwise it is assumed to be an older unencoded password.
2338  *
2339  */
2340 
2341 /*
2342  * encrypt_password - Encrypts a password string using DES
2343  * return: none
2344  * pass(in): string to encrypt
2345  * add_prefix(in): non-zero to add the prefix char
2346  * dest(out): destination buffer
2347  */
2348 static void
2349 encrypt_password (const char *pass, int add_prefix, char *dest)
2350 {
2351  if (pass == NULL)
2352  {
2353  strcpy (dest, "");
2354  }
2355  else
2356  {
2358  if (!add_prefix)
2359  {
2361  }
2362  else
2363  {
2364  crypt_encrypt_printable (pass, dest + 1, AU_MAX_PASSWORD_BUF);
2365  dest[0] = ENCODE_PREFIX_DES;
2366  }
2367  }
2368 }
2369 
2370 /*
2371  * encrypt_password_sha1 - hashing a password string using SHA1
2372  * return: none
2373  * pass(in): string to encrypt
2374  * add_prefix(in): non-zero to add the prefix char
2375  * dest(out): destination buffer
2376  */
2377 static void
2378 encrypt_password_sha1 (const char *pass, int add_prefix, char *dest)
2379 {
2380  if (pass == NULL)
2381  {
2382  strcpy (dest, "");
2383  }
2384  else
2385  {
2386  if (!add_prefix)
2387  {
2389  }
2390  else
2391  {
2393  dest[0] = ENCODE_PREFIX_SHA1;
2394  }
2395  }
2396 }
2397 
2398 /*
2399  * encrypt_password_sha2_512 - hashing a password string using SHA2 512
2400  * return: none
2401  * pass(in): string to encrypt
2402  * dest(out): destination buffer
2403  */
2404 static void
2405 encrypt_password_sha2_512 (const char *pass, char *dest)
2406 {
2407  int error_status = NO_ERROR;
2408  char *result_strp = NULL;
2409  int result_len = 0;
2410 
2411  if (pass == NULL)
2412  {
2413  strcpy (dest, "");
2414  }
2415  else
2416  {
2417  error_status = crypt_sha_two (NULL, pass, strlen (pass), 512, &result_strp, &result_len);
2418  if (error_status == NO_ERROR)
2419  {
2420  assert (result_strp != NULL);
2421 
2422  memcpy (dest + 1, result_strp, result_len);
2423  dest[result_len + 1] = '\0'; /* null termination for match_password () */
2424  dest[0] = ENCODE_PREFIX_SHA2_512;
2425 
2426  db_private_free_and_init (NULL, result_strp);
2427  }
2428  else
2429  {
2430  strcpy (dest, "");
2431  }
2432  }
2433 }
2434 
2435 /*
2436  * au_user_name_dup - Returns the duplicated string of the name of the current
2437  * user. The string must be freed after use.
2438  * return: user name (strdup)
2439  */
2440 char *
2442 {
2443  return strdup (Au_user_name);
2444 }
2445 
2446 /*
2447  * match_password - This compares two passwords to see if they match.
2448  * return: non-zero if the passwords match
2449  * user(in): user supplied password
2450  * database(in): stored database password
2451  *
2452  * Note: Either the user or database password can be encrypted or unencrypted.
2453  * The database password will only be unencrypted if this is a very
2454  * old database. The user password will be unencrypted if we're logging
2455  * in to an active session.
2456  */
2457 static bool
2458 match_password (const char *user, const char *database)
2459 {
2460  char buf1[AU_MAX_PASSWORD_BUF + 4];
2461  char buf2[AU_MAX_PASSWORD_BUF + 4];
2462 
2463  if (user == NULL || database == NULL)
2464  {
2465  return false;
2466  }
2467 
2468  /* get both passwords into an encrypted format */
2469  /* if database's password was encrypted with DES, then, user's password should be encrypted with DES, */
2470  if (IS_ENCODED_DES (database))
2471  {
2472  /* DB: DES */
2473  strcpy (buf2, database);
2474  if (IS_ENCODED_ANY (user))
2475  {
2476  /* USER : DES */
2477  strcpy (buf1, Au_user_password_des_oldstyle);
2478  }
2479  else
2480  {
2481  /* USER : PLAINTEXT -> DES */
2482  encrypt_password (user, 1, buf1);
2483  }
2484  }
2485  else if (IS_ENCODED_SHA1 (database))
2486  {
2487  /* DB: SHA1 */
2488  strcpy (buf2, database);
2489  if (IS_ENCODED_ANY (user))
2490  {
2491  /* USER:SHA1 */
2492  strcpy (buf1, Au_user_password_sha1);
2493  }
2494  else
2495  {
2496  /* USER:PLAINTEXT -> SHA1 */
2497  encrypt_password_sha1 (user, 1, buf1);
2498  }
2499  }
2500  else if (IS_ENCODED_SHA2_512 (database))
2501  {
2502  /* DB: SHA2 */
2503  strcpy (buf2, database);
2504  if (IS_ENCODED_ANY (user))
2505  {
2506  /* USER:SHA2 */
2507  strcpy (buf1, Au_user_password_sha2_512);
2508  }
2509  else
2510  {
2511  /* USER:PLAINTEXT -> SHA2 */
2512  encrypt_password_sha2_512 (user, buf1);
2513  }
2514  }
2515  else
2516  {
2517  /* DB:PLAINTEXT -> SHA2 */
2518  encrypt_password_sha2_512 (database, buf2);
2519  if (IS_ENCODED_ANY (user))
2520  {
2521  /* USER : SHA1 */
2522  strcpy (buf1, Au_user_password_sha1);
2523  }
2524  else
2525  {
2526  /* USER : PLAINTEXT -> SHA1 */
2527  encrypt_password_sha1 (user, 1, buf1);
2528  }
2529  }
2530 
2531  return strcmp (buf1, buf2) == 0;
2532 }
2533 
2534 /*
2535  * au_set_password_internal - Set the password string for a user.
2536  * This should be using encrypted strings.
2537  * return:error code
2538  * user(in): user object
2539  * password(in): new password
2540  * encode(in): flag to enable encryption of the string in the database
2541  * encrypt_prefix(in): If encode flag is 0, then we assume that the given password have been encrypted. So, All I have
2542  * to do is add prefix(SHA2) to given password.
2543  * If encode flag is 1, then we should encrypt password with sha2 and add prefix (SHA2) to it.
2544  * So, I don't care what encrypt_prefix value is.
2545  */
2546 static int
2547 au_set_password_internal (MOP user, const char *password, int encode, char encrypt_prefix)
2548 {
2549  int error = NO_ERROR;
2550  DB_VALUE value;
2551  MOP pass, pclass;
2552  int save, len;
2553  char pbuf[AU_MAX_PASSWORD_BUF + 4];
2554 
2555  AU_DISABLE (save);
2556  if (!ws_is_same_object (Au_user, user) && !au_is_dba_group_member (Au_user))
2557  {
2558  error = ER_AU_UPDATE_FAILURE;
2559  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2560  }
2561  else
2562  {
2563  /* convert empty password strings to NULL passwords */
2564  if (password != NULL)
2565  {
2566  len = strlen (password);
2567  if (len == 0)
2568  password = NULL;
2569  /*
2570  * check for large passwords, only do this
2571  * if the encode flag is on !
2572  */
2573  else if (len > AU_MAX_PASSWORD_CHARS && encode)
2574  {
2575  error = ER_AU_PASSWORD_OVERFLOW;
2576  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2577  }
2578  }
2579  if (error == NO_ERROR)
2580  {
2581  if ((error = obj_get (user, "password", &value)) == NO_ERROR)
2582  {
2583  if (DB_IS_NULL (&value))
2584  {
2585  pass = NULL;
2586  }
2587  else
2588  {
2589  pass = db_get_object (&value);
2590  }
2591 
2592  if (pass == NULL)
2593  {
2595  if (pclass != NULL)
2596  {
2597  pass = obj_create (pclass);
2598  if (pass != NULL)
2599  {
2600  db_make_object (&value, pass);
2601  error = obj_set (user, "password", &value);
2602  }
2603  else
2604  {
2605  assert (er_errid () != NO_ERROR);
2606  error = er_errid ();
2607  }
2608  }
2609  else
2610  {
2611  assert (er_errid () != NO_ERROR);
2612  error = er_errid ();
2613  }
2614  }
2615 
2616  if (error == NO_ERROR && pass != NULL)
2617  {
2618  if (encode && password != NULL)
2619  {
2620  encrypt_password_sha2_512 (password, pbuf);
2621  db_make_string (&value, pbuf);
2622  error = obj_set (pass, "password", &value);
2623  }
2624  else
2625  {
2626  /*
2627  * always add the prefix, the unload process strips it out
2628  * so the password can be read by the csql interpreter
2629  */
2630  if (password == NULL)
2631  {
2632  db_make_null (&value);
2633  }
2634  else
2635  {
2636  strcpy (pbuf + 1, password);
2637  pbuf[0] = encrypt_prefix;
2638  db_make_string (&value, pbuf);
2639  }
2640  error = obj_set (pass, "password", &value);
2641  }
2642  }
2643  }
2644  }
2645  }
2646  AU_ENABLE (save);
2647  return (error);
2648 }
2649 
2650 /*
2651  * au_set_password - Set the password string for a user.
2652  * return: error code
2653  * user(in): user object
2654  * password(in): new password
2655  */
2656 int
2657 au_set_password (MOP user, const char *password)
2658 {
2659  return (au_set_password_internal (user, password, 1, ENCODE_PREFIX_SHA2_512));
2660 }
2661 
2662 /*
2663  * au_set_password_method - Method interface for au_set_password.
2664  * return: none
2665  * user(in): user object
2666  * returnval(out): return value of this method
2667  * password(in): new password
2668  */
2669 void
2670 au_set_password_method (MOP user, DB_VALUE * returnval, DB_VALUE * password)
2671 {
2672  int error;
2673  const char *string = NULL;
2674 
2675  db_make_null (returnval);
2676  if (password != NULL)
2677  {
2678  if (IS_STRING (password) && !DB_IS_NULL (password))
2679  {
2680  string = db_get_string (password);
2681  }
2682 
2683  error = au_set_password (user, string);
2684  if (error != NO_ERROR)
2685  {
2686  db_make_error (returnval, error);
2687  }
2688  }
2689  else
2690  {
2691  error = ER_AU_INVALID_PASSWORD;
2693  db_make_error (returnval, error);
2694  }
2695 }
2696 
2697 /*
2698  * au_set_password_encoded_method - Method interface for setting
2699  * encoded passwords.
2700  * return: none
2701  * user(in): user object
2702  * returnval(out): return value of this object
2703  * password(in): new password
2704  *
2705  * Note: We don't check for the 8 character limit here because this is intended
2706  * to be used only by the schema generated by unloaddb. For this
2707  * application, the password length was validated when it was first
2708  * created.
2709  */
2710 void
2711 au_set_password_encoded_method (MOP user, DB_VALUE * returnval, DB_VALUE * password)
2712 {
2713  int error;
2714  const char *string = NULL;
2715 
2716  db_make_null (returnval);
2717  if (password != NULL)
2718  {
2719  if (IS_STRING (password))
2720  {
2721  if (DB_IS_NULL (password))
2722  {
2723  string = NULL;
2724  }
2725  else
2726  {
2727  string = db_get_string (password);
2728  }
2729  }
2730 
2731  error = au_set_password_internal (user, string, 0, ENCODE_PREFIX_DES);
2732  if (error != NO_ERROR)
2733  {
2734  db_make_error (returnval, error);
2735  }
2736  }
2737  else
2738  {
2739  error = ER_AU_INVALID_PASSWORD;
2741  db_make_error (returnval, error);
2742  }
2743 }
2744 
2745 /*
2746  * au_set_password_encoded_sha1_method - Method interface for setting sha1/2 passwords.
2747  * return: none
2748  * user(in): user object
2749  * returnval(out): return value of this object
2750  * password(in): new password
2751  *
2752  * Note: We don't check for the 8 character limit here because this is intended
2753  * to be used only by the schema generated by unloaddb. For this
2754  * application, the password length was validated when it was first
2755  * created.
2756  */
2757 void
2759 {
2760  int error;
2761  const char *string = NULL;
2762 
2763  db_make_null (returnval);
2764  if (password != NULL)
2765  {
2766  if (IS_STRING (password))
2767  {
2768  if (DB_IS_NULL (password))
2769  {
2770  string = NULL;
2771  }
2772  else
2773  {
2774  string = db_get_string (password);
2775  }
2776  }
2777 
2778  /* in case of SHA2, prefix is not stripped */
2779  if (string != NULL && IS_ENCODED_SHA2_512 (string))
2780  {
2781  error = au_set_password_internal (user, string + 1 /* 1 for prefix */ , 0, ENCODE_PREFIX_SHA2_512);
2782  }
2783  else
2784  {
2785  error = au_set_password_internal (user, string, 0, ENCODE_PREFIX_SHA1);
2786  }
2787 
2788  if (error != NO_ERROR)
2789  {
2790  db_make_error (returnval, error);
2791  }
2792  }
2793  else
2794  {
2795  error = ER_AU_INVALID_PASSWORD;
2797  db_make_error (returnval, error);
2798  }
2799 }
2800 
2801 /*
2802  * au_set_user_comment() - Set the comment string for a user.
2803  * return: error code
2804  * user(in): user object
2805  * comment(in): a comment string
2806  */
2807 int
2808 au_set_user_comment (MOP user, const char *comment)
2809 {
2810  int error = NO_ERROR;
2811  DB_VALUE value;
2812  int len = 0, save;
2813 
2814  AU_SAVE_AND_DISABLE (save);
2815  if (!ws_is_same_object (Au_user, user) && !au_is_dba_group_member (Au_user))
2816  {
2817  error = ER_AU_UPDATE_FAILURE;
2818  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2819  }
2820  else
2821  {
2822  if (comment != NULL)
2823  {
2824  len = strlen (comment);
2825  }
2826 
2827  if (len == 0)
2828  {
2829  comment = NULL;
2830  }
2831 
2832  if (len > AU_MAX_COMMENT_CHARS)
2833  {
2834  error = ER_AU_COMMENT_OVERFLOW;
2835  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2836  }
2837  else
2838  {
2839  db_make_string (&value, comment);
2840  error = obj_set (user, "comment", &value);
2841  pr_clear_value (&value);
2842  }
2843  }
2844  AU_RESTORE (save);
2845 
2846  return error;
2847 }
2848 
2849 /*
2850  * GROUP HIERARCHY MAINTENANCE
2851  */
2852 
2853 /*
2854  * au_add_direct_groups - Add the group to the new_groups and then add
2855  * the group's groups.
2856  * return: error status
2857  * new_groups(in):the set to add to
2858  * value(in): the group to add
2859  */
2860 static int
2861 au_add_direct_groups (DB_SET * new_groups, DB_VALUE * value)
2862 {
2863  int error;
2864  MOP group;
2865  DB_SET *direct_groups;
2866  int gcard, g;
2867  DB_VALUE gvalue;
2868 
2869  if ((error = db_set_add (new_groups, value)) == NO_ERROR)
2870  {
2871  if (DB_IS_NULL (value))
2872  {
2873  group = NULL;
2874  }
2875  else
2876  {
2877  group = db_get_object (value);
2878  }
2879  if ((error = au_get_set (group, "direct_groups", &direct_groups)) == NO_ERROR)
2880  {
2881  gcard = set_cardinality (direct_groups);
2882  for (g = 0; g < gcard && !error; g++)
2883  {
2884  if ((error = set_get_element (direct_groups, g, &gvalue)) == NO_ERROR)
2885  {
2886  error = au_add_direct_groups (new_groups, &gvalue);
2887  }
2888  }
2889  set_free (direct_groups);
2890  }
2891  }
2892 
2893  return error;
2894 }
2895 
2896 /*
2897  * au_compute_groups - Compute the groups attribute from the direct_groups
2898  * attribute for those users that have a particular
2899  * user/group in their groups attribute.
2900  * return: error status
2901  * member(in): the new member
2902  * name(in): the new member name
2903  */
2904 static int
2905 au_compute_groups (MOP member, const char *name)
2906 {
2907  int error = NO_ERROR;
2908  DB_SET *new_groups, *direct_groups;
2909  DB_VALUE value, gvalue, user_val;
2910  MOP user;
2911  int g, gcard;
2912  DB_SESSION *session;
2913  DB_VALUE val[3];
2914  STATEMENT_ID stmt_id;
2915  DB_QUERY_RESULT *result = (DB_QUERY_RESULT *) 0;
2916  const char *qstr = "select [d] from [db_user] [d] where ? in [d].[groups] or [d].[name] = ?;";
2917 
2918  db_make_object (&val[0], member);
2919  db_make_string (&val[1], name);
2920 
2921  session = db_open_buffer (qstr);
2922  if (!session)
2923  {
2924  assert (er_errid () != NO_ERROR);
2925  error = er_errid ();
2926  goto ret;
2927  }
2928 
2929  db_push_values (session, 2, val);
2930 
2931  stmt_id = db_compile_statement (session);
2932  if (stmt_id != 1)
2933  {
2934  assert (er_errid () != NO_ERROR);
2935  error = er_errid ();
2936  goto ret;
2937  }
2938 
2939  error = db_execute_statement_local (session, stmt_id, &result);
2940  if (error < 0)
2941  goto ret;
2942 
2943  /* error is row count if not negative. */
2944  if (error > 0)
2945  {
2946  error = NO_ERROR;
2947  while (db_query_next_tuple (result) == DB_CURSOR_SUCCESS)
2948  {
2949  if ((error = db_query_get_tuple_value (result, 0, &user_val)) == NO_ERROR)
2950  {
2951  if (DB_IS_NULL (&user_val))
2952  {
2953  user = NULL;
2954  }
2955  else
2956  {
2957  user = db_get_object (&user_val);
2958  }
2959  new_groups = set_create_basic ();
2960  if (new_groups)
2961  {
2962  if ((error = au_get_set (user, "direct_groups", &direct_groups)) == NO_ERROR)
2963  {
2964  /* compute closure */
2965  gcard = set_cardinality (direct_groups);
2966  for (g = 0; g < gcard && !error; g++)
2967  {
2968  if ((error = set_get_element (direct_groups, g, &gvalue)) == NO_ERROR)
2969  {
2970  error = au_add_direct_groups (new_groups, &gvalue);
2971  }
2972  }
2973  set_free (direct_groups);
2974  }
2975  }
2976  else
2977  {
2978  assert (er_errid () != NO_ERROR);
2979  error = er_errid ();
2980  }
2981  if (error == NO_ERROR)
2982  {
2983  db_make_set (&value, new_groups);
2984  obj_set (user, "groups", &value);
2985  }
2986  if (new_groups)
2987  {
2988  set_free (new_groups);
2989  }
2990  }
2991  }
2992  }
2993 
2994 ret:
2995  if (result)
2996  {
2997  db_query_end (result);
2998  }
2999  if (session)
3000  {
3001  db_close_session (session);
3002  }
3003 
3004  return error;
3005 }
3006 
3007 /*
3008  * au_add_member_internal - Add a member to a group and propagate the member
3009  * to all affected sub-groups. If the call is
3010  * for a new user, then no other user can be part of
3011  * this user(group)
3012  * return: error status
3013  * group(in): group to get new member
3014  * member(in): the new member
3015  * new_user(in): whether the call is for a new user
3016  *
3017  * Note:
3018  * the db_user class used to have a groups and a members attribute. the
3019  * members attribute was eliminated as a performance improvement, but the
3020  * direct_groups attribute has been added. both groups and direct_groups
3021  * are sets. the direct_groups attribute indicates which groups the user/
3022  * group is an immediate member of. the groups attribute indicates which
3023  * groups the user/group is a member of (immediate or otherwise). the
3024  * group attribute is a flattened set. when a user/group is added to a
3025  * new group, the new group is added to both the direct_groups and groups
3026  * attributes for the user/group. then that change is propagated to other
3027  * users/groups.
3028  * for example, if u1 is in g1 and g1 is added to g2, g2 is added to g1's
3029  * direct_groups and groups attributes and g2 is also added to u1's groups
3030  * attributes.
3031  */
3032 static int
3033 au_add_member_internal (MOP group, MOP member, int new_user)
3034 {
3035  int error = NO_ERROR;
3036  DB_VALUE membervalue, member_name_val, groupvalue;
3037  DB_SET *group_groups = NULL, *member_groups = NULL, *member_direct_groups = NULL;
3038  int save;
3039  const char *member_name = NULL;
3040 
3041  AU_DISABLE (save);
3042  db_make_object (&membervalue, member);
3043  db_make_object (&groupvalue, group);
3044 
3045  /*
3046  * Skip some checks and processing for a new user/group because it
3047  * can't have any members yet.
3048  */
3049  if ((!new_user) && (group == member))
3050  {
3053  }
3054  else
3055  {
3056  if ((!new_user) && ((error = au_get_set (group, "groups", &group_groups)) != NO_ERROR))
3057  {
3058  ;
3059  }
3060  else
3061  {
3062  if ((!new_user) && (set_ismember (group_groups, &membervalue)))
3063  {
3066  }
3067  else
3068  {
3069  error = obj_inst_lock (member, 1);
3070  if (error == NO_ERROR)
3071  {
3072  error = au_get_set (member, "groups", &member_groups);
3073  }
3074 
3075  if (error == NO_ERROR)
3076  {
3077  error = au_get_set (member, "direct_groups", &member_direct_groups);
3078  if (error == NO_ERROR)
3079  {
3080  if (new_user)
3081  {
3082  error = db_set_add (member_groups, &groupvalue);
3083  if (error == NO_ERROR)
3084  {
3085  error = db_set_add (member_direct_groups, &groupvalue);
3086  }
3087  }
3088  else if (!set_ismember (member_direct_groups, &membervalue))
3089  {
3090  error = db_get (member, "name", &member_name_val);
3091  if (error == NO_ERROR)
3092  {
3093  if (DB_IS_NULL (&member_name_val))
3094  {
3095  member_name = NULL;
3096  }
3097  else
3098  {
3099  member_name = db_get_string (&member_name_val);
3100  }
3101 
3102  error = db_set_add (member_direct_groups, &groupvalue);
3103  if (error == NO_ERROR)
3104  {
3105  error = au_compute_groups (member, member_name);
3106  }
3107  db_value_clear (&member_name_val);
3108  }
3109  }
3110  set_free (member_direct_groups);
3111  }
3112  set_free (member_groups);
3113  }
3114 
3115  if (!new_user)
3116  {
3117  set_free (group_groups);
3118  }
3119  }
3120  }
3121  }
3122  AU_ENABLE (save);
3123  return (error);
3124 }
3125 
3126 /*
3127  * au_add_member - Add a member to a group and propagate the member to
3128  * all affected sub-groups.
3129  * return: error status
3130  * group(in): group to get new member
3131  * member(in): the new member
3132  */
3133 int
3134 au_add_member (MOP group, MOP member)
3135 {
3136  return au_add_member_internal (group, member, 0);
3137 }
3138 
3139 /*
3140  * au_add_member_method - Method interface to au_add_member.
3141  * return: none
3142  * user(in): user object
3143  * returnval(out): return value of this method
3144  * memval(in):
3145  */
3146 void
3147 au_add_member_method (MOP user, DB_VALUE * returnval, DB_VALUE * memval)
3148 {
3149  int error = NO_ERROR;
3150  MOP member;
3151 
3152  if (memval != NULL)
3153  {
3154  member = NULL;
3155  if (DB_VALUE_TYPE (memval) == DB_TYPE_OBJECT && !DB_IS_NULL (memval) && db_get_object (memval) != NULL)
3156  {
3157  member = db_get_object (memval);
3158  }
3159  else if (IS_STRING (memval) && !DB_IS_NULL (memval) && db_get_string (memval) != NULL)
3160  {
3161  member = au_find_user (db_get_string (memval));
3162  if (member == NULL)
3163  {
3164  assert (er_errid () != NO_ERROR);
3165  error = er_errid ();
3166  goto error;
3167  }
3168  }
3169 
3170  if (member != NULL)
3171  {
3172  if (ws_is_same_object (user, Au_user) || au_is_dba_group_member (Au_user))
3173  {
3174  error = au_add_member (user, member);
3175  }
3176  else
3177  {
3178  error = ER_AU_NOT_OWNER;
3180  }
3181  }
3182  else
3183  {
3184  error = ER_AU_INVALID_USER;
3185  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
3186  }
3187  }
3188  else
3189  {
3190  error = ER_AU_INVALID_USER;
3191  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
3192  }
3193 
3194 error:
3195  if (error == NO_ERROR)
3196  {
3197  db_make_null (returnval);
3198  }
3199  else
3200  {
3201  db_make_error (returnval, error);
3202  }
3203 }
3204 
3205 /*
3206  * au_drop_member - Remove a member from a group.
3207  * return: error code
3208  * group(in): group with member to drop
3209  * member(in): member to drop
3210  *
3211  * Note:
3212  *
3213  * The db_user class used to have a groups and a members attribute. The
3214  * members attribute was eliminated as a performance improvement, but the
3215  * direct_groups attribute has been added. Both groups and direct_groups
3216  * are sets. The direct_groups attribute indicates which groups the user/
3217  * group is an immediate member of. The groups attribute indicates which
3218  * groups the user/group is a member of (immediate or otherwise). The
3219  * groups attribute is a flattened set. When a user/group is dropped from
3220  * a group, the group is removed from both the direct_groups and groups
3221  * attributes for the user/group. Then that change is propagated to other
3222  * users/groups.
3223  * For example, if U1 is directly in G1 and G1 is directly in G2 and G1
3224  * is dropped from G2, G2 is removed from G1's direct_groups and groups
3225  * attributes and G2 is also removed from U1's groups attribute.
3226  */
3227 int
3228 au_drop_member (MOP group, MOP member)
3229 {
3230  int syserr = NO_ERROR, error = NO_ERROR;
3231  DB_VALUE groupvalue, member_name_val;
3232  DB_SET *groups = NULL, *member_groups = NULL, *member_direct_groups = NULL;
3233  int save;
3234  const char *member_name = NULL;
3235 
3236  AU_DISABLE (save);
3237  db_make_object (&groupvalue, group);
3238 
3239  if ((syserr = au_get_set (member, "groups", &member_groups)) == NO_ERROR)
3240  {
3241  if (!set_ismember (member_groups, &groupvalue))
3242  {
3243  error = ER_AU_MEMBER_NOT_FOUND;
3245  }
3246  else if ((error = au_get_set (group, "groups", &groups)) == NO_ERROR)
3247  {
3248  if (set_ismember (groups, &groupvalue))
3249  {
3250  error = ER_AU_MEMBER_NOT_FOUND;
3252  }
3253  else
3254  {
3255  error = obj_inst_lock (member, 1);
3256  if (error == NO_ERROR)
3257  {
3258  error = au_get_set (member, "direct_groups", &member_direct_groups);
3259  }
3260 
3261  if (error == NO_ERROR)
3262  {
3263  if ((error = db_get (member, "name", &member_name_val)) == NO_ERROR)
3264  {
3265  if (DB_IS_NULL (&member_name_val))
3266  {
3267  member_name = NULL;
3268  }
3269  else
3270  {
3271  member_name = db_get_string (&member_name_val);
3272  }
3273  if ((error = db_set_drop (member_direct_groups, &groupvalue)) == NO_ERROR)
3274  {
3275  error = au_compute_groups (member, member_name);
3276  }
3277  db_value_clear (&member_name_val);
3278  }
3279  set_free (member_direct_groups);
3280  }
3281  }
3282  set_free (groups);
3283  }
3284  set_free (member_groups);
3285  }
3286  AU_ENABLE (save);
3287  return (error);
3288 }
3289 
3290 /*
3291  * au_drop_member_method - Method interface for au_drop_member.
3292  * return: none
3293  * user(in): user object
3294  * returnval(in): return value of this method
3295  * memval(in):
3296  */
3297 void
3298 au_drop_member_method (MOP user, DB_VALUE * returnval, DB_VALUE * memval)
3299 {
3300  int error = NO_ERROR;
3301  MOP member;
3302 
3303  if (memval != NULL)
3304  {
3305  member = NULL;
3306  if (DB_VALUE_TYPE (memval) == DB_TYPE_OBJECT && !DB_IS_NULL (memval) && db_get_object (memval) != NULL)
3307  {
3308  member = db_get_object (memval);
3309  }
3310  else if (IS_STRING (memval) && !DB_IS_NULL (memval) && db_get_string (memval) != NULL)
3311  {
3312  member = au_find_user (db_get_string (memval));
3313  if (member == NULL)
3314  {
3315  assert (er_errid () != NO_ERROR);
3316  error = er_errid ();
3317  goto error;
3318  }
3319  }
3320 
3321  if (member != NULL)
3322  {
3323  if (ws_is_same_object (user, Au_user) || au_is_dba_group_member (Au_user))
3324  {
3325  error = au_drop_member (user, member);
3326  }
3327  else
3328  {
3329  error = ER_AU_NOT_OWNER;
3331  }
3332  }
3333  else
3334  {
3335  error = ER_AU_INVALID_USER;
3336  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
3337  }
3338  }
3339  else
3340  {
3341  error = ER_AU_INVALID_USER;
3342  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
3343  }
3344 
3345 error:
3346  if (error == NO_ERROR)
3347  {
3348  db_make_null (returnval);
3349  }
3350  else
3351  {
3352  db_make_error (returnval, error);
3353  }
3354 }
3355 
3356 /*
3357  * au_drop_user - Drop a user from the database.
3358  * return: error code
3359  * user(in): user object
3360  *
3361  * Note:
3362  *
3363  * This should only be called with DBA privilidges.
3364  * The db_user class used to have a groups and a members attribute. The
3365  * members attribute was eliminated as a performance improvement, but the
3366  * direct_groups attribute has been added. Both groups and direct_groups
3367  * are sets. The direct_groups attribute indicates which groups the user/
3368  * group is an immediate member of. The groups attribute indicates which
3369  * groups the user/group is a member of (immediate or otherwise). The
3370  * groups attribute is a flattened set. When a user/group is dropped,
3371  * the user/group is removed from both the direct_groups and groups
3372  * attributes for all users. For example, if U1 is directly in G1 and G1
3373  * is directly in G2 and G1 is dropped, G1 & G2 are removed from U1's
3374  * groups attribute and G1 is also removed from U1's direct_groups
3375  * attribute.
3376  */
3377 int
3379 {
3380  int save;
3381  DB_SESSION *session = NULL;
3382  DB_VALUE val[2], user_val, gvalue, value, password_val;
3383  STATEMENT_ID stmt_id;
3384  int error = NO_ERROR;
3385  DB_QUERY_RESULT *result;
3386  MOP auser, password;
3387  DB_SET *new_groups, *direct_groups;
3388  int g, gcard, i;
3389  DB_VALUE name;
3390  const char *class_name[] = {
3391  /*
3392  * drop user command can be called only by DBA group,
3393  * so we can use query for _db_class directly
3394  */
3395  "_db_class", "db_trigger", "db_serial", NULL
3396  };
3397  char query_buf[1024];
3398 
3399  AU_DISABLE (save);
3400 
3401  if (Au_dba_user != NULL && !au_is_dba_group_member (Au_user))
3402  {
3403  error = ER_AU_DBA_ONLY;
3404  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "drop_user");
3405  goto error;
3406  }
3407 
3408  /* check if user is dba/public or current user */
3409  if (ws_is_same_object (user, Au_dba_user) || ws_is_same_object (user, Au_public_user)
3410  || ws_is_same_object (user, Au_user))
3411  {
3412  db_make_null (&name);
3413  error = obj_get (user, "name", &name);
3414  if (error != NO_ERROR)
3415  {
3416  goto error;
3417  }
3418 
3419  error = ER_AU_CANT_DROP_USER;
3420  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, db_get_string (&name));
3421  goto error;
3422  }
3423 
3424  /* check if user owns class/vclass/trigger/serial */
3425  for (i = 0; class_name[i] != NULL; i++)
3426  {
3427  sprintf (query_buf, "select count(*) from [%s] where [owner] = ?;", class_name[i]);
3428  session = db_open_buffer (query_buf);
3429  if (session == NULL)
3430  {
3431  goto error;
3432  }
3433 
3434  db_make_object (&val[0], user);
3435  db_push_values (session, 1, &val[0]);
3436  stmt_id = db_compile_statement (session);
3437  if (stmt_id != 1)
3438  {
3439  assert (er_errid () != NO_ERROR);
3440  error = er_errid ();
3441  db_close_session (session);
3442  goto error;
3443  }
3444 
3445  error = db_execute_statement_local (session, stmt_id, &result);
3446  if (error < 0)
3447  {
3448  db_close_session (session);
3449  goto error;
3450  }
3451 
3452  error = db_query_first_tuple (result);
3453  if (error < 0)
3454  {
3455  db_query_end (result);
3456  db_close_session (session);
3457  goto error;
3458  }
3459 
3460  db_make_int (&value, 0);
3461  error = db_query_get_tuple_value (result, 0, &value);
3462  if (error != NO_ERROR)
3463  {
3464  db_query_end (result);
3465  db_close_session (session);
3466  goto error;
3467  }
3468 
3469  if (db_get_int (&value) > 0)
3470  {
3472  db_query_end (result);
3473  db_close_session (session);
3475  goto error;
3476  }
3477 
3478  db_query_end (result);
3479  db_close_session (session);
3480  pr_clear_value (&val[0]);
3481  }
3482 
3483 
3484  /* propagate user deletion to groups */
3485  db_make_object (&val[1], user);
3486 
3487  session =
3488  db_open_buffer ("update [db_user] [d] set "
3489  "[d].[direct_groups] = [d].[direct_groups] - ? where ? in [d].[direct_groups];");
3490  if (session == NULL)
3491  {
3492  assert (er_errid () != NO_ERROR);
3493  error = er_errid ();
3494  goto error;
3495  }
3496 
3497  new_groups = set_create_basic ();
3498  if (new_groups)
3499  {
3500  error = db_set_add (new_groups, &val[1]);
3501  if (error == NO_ERROR)
3502  {
3503  db_make_set (&val[0], new_groups);
3504  db_push_values (session, 2, val);
3505  stmt_id = db_compile_statement (session);
3506  if (stmt_id == 1)
3507  {
3508  error = db_execute_statement_local (session, stmt_id, &result);
3509  db_query_end (result);
3510  }
3511  else
3512  {
3513  assert (er_errid () != NO_ERROR);
3514  error = er_errid ();
3515  }
3516  }
3517  /*
3518  * We need to clear the host variable here to free the set. set_free()
3519  * is not sufficient since the set referenced by new_groups may have
3520  * be replaced as a result of tp_value_cast().
3521  */
3522  pr_clear_value (&val[0]);
3523  }
3524 
3525  db_close_session (session);
3526  if (error < NO_ERROR)
3527  {
3528  goto error;
3529  }
3530 
3531  session = db_open_buffer ("select [d] from [db_user] [d] where ? in [d].[groups];");
3532  if (session == NULL)
3533  {
3534  assert (er_errid () != NO_ERROR);
3535  error = er_errid ();
3536  goto error;
3537  }
3538 
3539  db_push_values (session, 1, &val[1]);
3540  stmt_id = db_compile_statement (session);
3541  if (stmt_id == 1)
3542  {
3543  error = db_execute_statement_local (session, stmt_id, &result);
3544  if (error > 0)
3545  {
3546  error = NO_ERROR;
3547  while (error == NO_ERROR && db_query_next_tuple (result) == DB_CURSOR_SUCCESS)
3548  {
3549  error = db_query_get_tuple_value (result, 0, &user_val);
3550  if (error == NO_ERROR)
3551  {
3552  if (DB_IS_NULL (&user_val))
3553  {
3554  auser = NULL;
3555  }
3556  else
3557  {
3558  auser = db_get_object (&user_val);
3559  }
3560 
3561  new_groups = set_create_basic ();
3562  if (new_groups)
3563  {
3564  error = au_get_set (auser, "direct_groups", &direct_groups);
3565  if (error == NO_ERROR)
3566  {
3567  /* compute closure */
3568  gcard = set_cardinality (direct_groups);
3569  for (g = 0; g < gcard && !error; g++)
3570  {
3571  error = set_get_element (direct_groups, g, &gvalue);
3572  if (error == NO_ERROR)
3573  {
3574  error = au_add_direct_groups (new_groups, &gvalue);
3575  }
3576  }
3577  set_free (direct_groups);
3578  }
3579  }
3580  else
3581  {
3582  assert (er_errid () != NO_ERROR);
3583  error = er_errid ();
3584  }
3585 
3586  if (error == NO_ERROR)
3587  {
3588  db_make_set (&value, new_groups);
3589  obj_set (auser, "groups", &value);
3590  }
3591 
3592  if (new_groups)
3593  {
3594  set_free (new_groups);
3595  }
3596  }
3597  }
3598  }
3599  db_query_end (result);
3600  }
3601  else
3602  {
3603  assert (er_errid () != NO_ERROR);
3604  error = er_errid ();
3605  }
3606 
3607  db_close_session (session);
3608  if (error < NO_ERROR)
3609  {
3610  goto error;
3611  }
3612 
3613  db_make_null (&password_val);
3614  error = obj_get (user, "password", &password_val);
3615  if (!DB_IS_NULL (&password_val))
3616  {
3617  password = db_get_object (&password_val);
3618  error = obj_delete (password);
3619  if (error == NO_ERROR)
3620  {
3621  db_make_null (&password_val);
3622  error = obj_set (user, "password", &password_val);
3623  }
3624 
3625  if (error != NO_ERROR)
3626  {
3627  goto error;
3628  }
3629  }
3630 
3631  /*
3632  * could go through classes created by this user and change ownership
3633  * to the DBA ? - do this as the classes are referenced instead
3634  */
3635 
3636  error = obj_delete (user);
3637  if (error == NO_ERROR)
3638  {
3640  }
3641 
3642 error:
3643  AU_ENABLE (save);
3644  return error;
3645 }
3646 
3647 /*
3648  * au_drop_user_method - Method interface for au_drop_user.
3649  * return: none
3650  * root(in):
3651  * returnval(out): return value of this method
3652  * name(in):
3653  */
3654 void
3655 au_drop_user_method (MOP root, DB_VALUE * returnval, DB_VALUE * name)
3656 {
3657  int error;
3658  DB_OBJECT *user = NULL;
3659 
3660  db_make_null (returnval);
3661 
3662  if (Au_dba_user != NULL && !au_is_dba_group_member (Au_user))
3663  {
3664  error = ER_AU_DBA_ONLY;
3665  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "drop_user");
3666  db_make_error (returnval, error);
3667  }
3668  else
3669  {
3670  user = NULL;
3671  if (name != NULL && IS_STRING (name) && db_get_string (name) != NULL)
3672  {
3673  error = au_find_user_to_drop (db_get_string (name), &user);
3674  if (error == NO_ERROR)
3675  {
3676  assert (user != NULL);
3677  error = au_drop_user (user);
3678  }
3679 
3680  if (error != NO_ERROR)
3681  {
3682  db_make_error (returnval, error);
3683  }
3684  }
3685  else
3686  {
3687  error = ER_AU_INVALID_USER;
3688  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
3689  db_make_error (returnval, error);
3690  }
3691  }
3692 }
3693 
3694 
3695 /*
3696  * AUTHORIZATION CACHING
3697  */
3698 
3699 /*
3700  * find_grant_entry - This searches a sequence of grant elements looking for
3701  * a grant from a particular user on a particular class.
3702  * return: sequence index to grant entry
3703  * grants(in): sequence of grant information
3704  * class_mop(in): class to look for
3705  * grantor(in): user who made the grant
3706  *
3707  * Note: It returns the index into the sequence where the grant information
3708  * is found. If the grant was not found it returns -1.
3709  */
3710 static int
3711 find_grant_entry (DB_SET * grants, MOP class_mop, MOP grantor)
3712 {
3713  DB_VALUE element;
3714  int i, gsize, position;
3715 
3716  position = -1;
3717  gsize = set_size (grants);
3718  for (i = 0; i < gsize && position == -1; i += GRANT_ENTRY_LENGTH)
3719  {
3720  set_get_element (grants, GRANT_ENTRY_CLASS (i), &element);
3721  if (db_get_object (&element) == class_mop)
3722  {
3723  set_get_element (grants, GRANT_ENTRY_SOURCE (i), &element);
3724  if (ws_is_same_object (db_get_object (&element), grantor))
3725  {
3726  position = i;
3727  }
3728  }
3729  }
3730 
3731  return position;
3732 }
3733 
3734 /*
3735  * add_grant_entry - This adds a grant on a class from a particular user to
3736  * a sequence of grant elemetns.
3737  * It returns the index of the new grant element.
3738  * return: sequence index to new grant entry
3739  * grants(in): grant sequence to extend
3740  * class_mop(in): class being granted
3741  * grantor(in): user doing the granting
3742  */
3743 static int
3744 add_grant_entry (DB_SET * grants, MOP class_mop, MOP grantor)
3745 {
3746  DB_VALUE value;
3747  int index;
3748 
3749  index = set_size (grants);
3750 
3751  db_make_object (&value, class_mop);
3752  set_put_element (grants, GRANT_ENTRY_CLASS (index), &value);
3753 
3754  db_make_object (&value, grantor);
3755  set_put_element (grants, GRANT_ENTRY_SOURCE (index), &value);
3756 
3757  db_make_int (&value, 0);
3758  set_put_element (grants, GRANT_ENTRY_CACHE (index), &value);
3759 
3760  return (index);
3761 }
3762 
3763 /*
3764  * drop_grant_entry - This removes a grant element at a particular location
3765  * and shifts all subsequent grant elements up to fill
3766  * in the empty space.
3767  * return: none
3768  * grants(in): grant sequence
3769  * index(in): index of grant element to remove
3770  */
3771 static void
3773 {
3774  int i;
3775 
3776  /* not particularly fast but doesn't happen very often */
3777  if (set_size (grants) >= (index + GRANT_ENTRY_LENGTH))
3778  {
3779  for (i = 0; i < GRANT_ENTRY_LENGTH; i++)
3780  {
3781  set_drop_seq_element (grants, index);
3782  }
3783  }
3784 }
3785 
3786 /*
3787  * get_grants - This gets the grant set from an authorization object,
3788  * VERY CAREFULLY.
3789  * return: error code
3790  * auth(in): authorization object
3791  * grant_ptr(out): return grant set
3792  * filter(in):
3793  *
3794  */
3795 static int
3796 get_grants (MOP auth, DB_SET ** grant_ptr, int filter)
3797 {
3798  int error = NO_ERROR;
3799  DB_VALUE value;
3800  DB_SET *grants = NULL;
3801  MOP grantor, gowner, class_;
3802  int gsize, i, j, existing, cache;
3803  bool need_pop_er_stack = false;
3804 
3805  assert (grant_ptr != NULL);
3806 
3807  *grant_ptr = NULL;
3808 
3809  er_stack_push ();
3810 
3811  need_pop_er_stack = true;
3812 
3813  error = obj_get (auth, "grants", &value);
3814  if (error != NO_ERROR)
3815  {
3816  goto end;
3817  }
3818 
3819  if (DB_VALUE_TYPE (&value) != DB_TYPE_SEQUENCE || DB_IS_NULL (&value) || db_get_set (&value) == NULL)
3820  {
3821  error = ER_AU_CORRUPTED;
3822  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
3823 
3824  goto end;
3825  }
3826 
3827  if (!filter)
3828  {
3829  goto end;
3830  }
3831 
3832  grants = db_get_set (&value);
3833  gsize = set_size (grants);
3834 
3835  /* there might be errors */
3836  error = er_errid ();
3837  if (error != NO_ERROR)
3838  {
3839  goto end;
3840  }
3841 
3842  for (i = 0; i < gsize; i += GRANT_ENTRY_LENGTH)
3843  {
3844  error = set_get_element (grants, GRANT_ENTRY_SOURCE (i), &value);
3845  if (error != NO_ERROR)
3846  {
3847  goto end;
3848  }
3849 
3850  grantor = NULL;
3851  if (DB_VALUE_TYPE (&value) == DB_TYPE_OBJECT && !DB_IS_NULL (&value))
3852  {
3853  grantor = db_get_object (&value);
3854  if (WS_IS_DELETED (grantor))
3855  {
3856  grantor = NULL;
3857  }
3858  }
3859 
3860  if (grantor == NULL)
3861  {
3862  class_ = NULL;
3863  error = set_get_element (grants, GRANT_ENTRY_CLASS (i), &value);
3864  if (error != NO_ERROR)
3865  {
3866  goto end;
3867  }
3868 
3869  if (DB_VALUE_TYPE (&value) == DB_TYPE_OBJECT && !DB_IS_NULL (&value))
3870  {
3871  class_ = db_get_object (&value);
3872  if (WS_IS_DELETED (class_))
3873  {
3874  class_ = NULL;
3875  }
3876  }
3877 
3878  if (class_ == NULL)
3879  {
3880  /* class is bad too, remove this entry */
3881  drop_grant_entry (grants, i);
3882  gsize -= GRANT_ENTRY_LENGTH;
3883  }
3884  else
3885  {
3886  /* this will at least be DBA */
3887  gowner = au_get_class_owner (class_);
3888 
3889  /* see if there's already an entry for this */
3890  existing = -1;
3891  for (j = 0; j < gsize && existing == -1; j += GRANT_ENTRY_LENGTH)
3892  {
3893  error = set_get_element (grants, GRANT_ENTRY_SOURCE (j), &value);
3894  if (error != NO_ERROR)
3895  {
3896  goto end;
3897  }
3898 
3899  if (DB_VALUE_TYPE (&value) == DB_TYPE_OBJECT && ws_is_same_object (db_get_object (&value), gowner))
3900  {
3901  existing = j;
3902  }
3903  }
3904 
3905  if (existing == -1)
3906  {
3907  /*
3908  * no previous entry for the owner,
3909  * use the current one
3910  */
3911  db_make_object (&value, gowner);
3912  error = set_put_element (grants, GRANT_ENTRY_SOURCE (i), &value);
3913  if (error != NO_ERROR)
3914  {
3915  goto end;
3916  }
3917  }
3918  else
3919  {
3920  /*
3921  * update the previous entry with the extra bits
3922  * and delete the current entry
3923  */
3924  error = set_get_element (grants, GRANT_ENTRY_CACHE (i), &value);
3925  if (error != NO_ERROR)
3926  {
3927  goto end;
3928  }
3929 
3930  cache = db_get_int (&value);
3931  error = set_get_element (grants, GRANT_ENTRY_CACHE (existing), &value);
3932  if (error != NO_ERROR)
3933  {
3934  goto end;
3935  }
3936 
3937  db_make_int (&value, db_get_int (&value) | cache);
3938  error = set_put_element (grants, GRANT_ENTRY_CACHE (existing), &value);
3939  if (error != NO_ERROR)
3940  {
3941  goto end;
3942  }
3943 
3944  drop_grant_entry (grants, i);
3945  gsize -= GRANT_ENTRY_LENGTH;
3946  }
3947  }
3948  }
3949  }
3950 
3951 end:
3952 
3953  if (error != NO_ERROR && grants != NULL)
3954  {
3955  set_free (grants);
3956  grants = NULL;
3957  }
3958 
3959  if (need_pop_er_stack)
3960  {
3961  if (error == NO_ERROR)
3962  {
3963  er_stack_pop ();
3964  }
3965  else
3966  {
3968  }
3969  }
3970 
3971  *grant_ptr = grants;
3972  return (error);
3973 }
3974 
3975 /*
3976  * apply_grants - Work function for update_cache.
3977  * return: error code
3978  * auth(in): authorization object
3979  * class(in): class being authorized
3980  * bits(in):
3981  *
3982  * Note: Get the grant information for an authorization object and update
3983  * the cache for any grants that apply to the class.
3984  */
3985 static int
3986 apply_grants (MOP auth, MOP class_mop, unsigned int *bits)
3987 {
3988  int error = NO_ERROR;
3989  DB_SET *grants;
3990  DB_VALUE grvalue;
3991  int i, gsize;
3992 
3993  error = get_grants (auth, &grants, 1);
3994  if (error == NO_ERROR)
3995  {
3996  gsize = set_size (grants);
3997  for (i = 0; i < gsize; i += GRANT_ENTRY_LENGTH)
3998  {
3999  set_get_element (grants, GRANT_ENTRY_CLASS (i), &grvalue);
4000  if (db_get_object (&grvalue) == class_mop)
4001  {
4002  set_get_element (grants, GRANT_ENTRY_CACHE (i), &grvalue);
4003  *bits |= db_get_int (&grvalue);
4004  }
4005  }
4006  set_free (grants);
4007  }
4008 
4009  return (error);
4010 }
4011 
4012 /*
4013  * update_cache - This is the main function for parsing all of
4014  * the authorization information for a particular class and
4015  * caching it in the class structure.
4016  * This will be called once after each successful
4017  * read/write lock. It needs to be fast.
4018  * return: error code
4019  * classop(in): class MOP to authorize
4020  * sm_class(in): direct pointer to class structure
4021  * cache(in):
4022  */
4023 static int
4024 update_cache (MOP classop, SM_CLASS * sm_class, AU_CLASS_CACHE * cache)
4025 {
4026  int error = NO_ERROR;
4027  DB_SET *groups = NULL;
4028  int i, save, card;
4029  DB_VALUE value;
4030  MOP group, auth;
4031  unsigned int *bits;
4032  bool is_member = false;
4033  bool need_pop_er_stack = false;
4034 
4035  /*
4036  * must disable here because we may be updating the cache of the system
4037  * objects and we need to read them in order to update etc.
4038  */
4039  AU_DISABLE (save);
4040 
4041  er_stack_push ();
4042 
4043  need_pop_er_stack = true;
4044 
4045  bits = &cache->data[Au_cache_index];
4046 
4047  /* initialize the cache bits */
4048  *bits = AU_NO_AUTHORIZATION;
4049 
4050  if (sm_class->owner == NULL)
4051  {
4052  /* This shouldn't happen - assign it to the DBA */
4053  error = ER_AU_CLASS_WITH_NO_OWNER;
4054  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
4055 
4056  goto end;
4057  }
4058 
4059  is_member = au_is_dba_group_member (Au_user);
4060  if (is_member)
4061  {
4062  *bits = AU_FULL_AUTHORIZATION;
4063 
4064  goto end;
4065  }
4066 
4067  /* there might be errors */
4068  error = er_errid ();
4069  if (error != NO_ERROR)
4070  {
4071  goto end;
4072  }
4073 
4074  if (ws_is_same_object (Au_user, sm_class->owner))
4075  {
4076  /* might want to allow grant/revoke on self */
4077  *bits = AU_FULL_AUTHORIZATION;
4078 
4079  goto end;
4080  }
4081 
4082  if (au_get_set (Au_user, "groups", &groups) != NO_ERROR)
4083  {
4084  error = ER_AU_ACCESS_ERROR;
4085  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 2, "groups", AU_USER_CLASS_NAME);
4086 
4087  goto end;
4088  }
4089 
4090  db_make_object (&value, sm_class->owner);
4091 
4092  is_member = set_ismember (groups, &value);
4093 
4094  /* there might be errors */
4095  error = er_errid ();
4096  if (error != NO_ERROR)
4097  {
4098  goto end;
4099  }
4100 
4101  if (is_member)
4102  {
4103  /* we're a member of the owning group */
4104  *bits = AU_FULL_AUTHORIZATION;
4105  }
4106  else if (au_get_object (Au_user, "authorization", &auth) != NO_ERROR)
4107  {
4108  error = ER_AU_ACCESS_ERROR;
4109  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 2, "authorization", AU_USER_CLASS_NAME);
4110  }
4111  else
4112  {
4113  /* apply local grants */
4114  error = apply_grants (auth, classop, bits);
4115  if (error != NO_ERROR)
4116  {
4117  goto end;
4118  }
4119 
4120  /* apply grants from all groups */
4121  card = set_cardinality (groups);
4122 
4123  /* there might be errors */
4124  error = er_errid ();
4125  if (error != NO_ERROR)
4126  {
4127  goto end;
4128  }
4129 
4130  for (i = 0; i < card; i++)
4131  {
4132  /* will have to handle deleted groups here ! */
4133  error = au_set_get_obj (groups, i, &group);
4134  if (error != NO_ERROR)
4135  {
4136  goto end;
4137  }
4138 
4139  if (ws_is_same_object (group, Au_dba_user))
4140  {
4141  /* someones on the DBA member list, give them power */
4142  *bits = AU_FULL_AUTHORIZATION;
4143  }
4144  else
4145  {
4146  error = au_get_object (group, "authorization", &auth);
4147  if (error != NO_ERROR)
4148  {
4149  goto end;
4150  }
4151 
4152  error = apply_grants (auth, classop, bits);
4153  if (error != NO_ERROR)
4154  {
4155  goto end;
4156  }
4157  }
4158  }
4159  }
4160 
4161 end:
4162 
4163  if (groups != NULL)
4164  {
4165  set_free (groups);
4166  }
4167 
4168  if (need_pop_er_stack)
4169  {
4170  if (error == NO_ERROR)
4171  {
4172  er_stack_pop ();
4173  }
4174  else
4175  {
4177  }
4178  }
4179 
4180  AU_ENABLE (save);
4181 
4182  return (error);
4183 }
4184 
4185 /*
4186  * appropriate_error - This selects an appropriate error code to correspond
4187  * with an authorization failure of a some type
4188  * return: error code
4189  * bits(in): authorization type
4190  * requested(in):
4191  * TODO : LP64
4192  */
4193 static int
4194 appropriate_error (unsigned int bits, unsigned int requested)
4195 {
4196  int error;
4197  unsigned int mask, atype;
4198  int i;
4199 
4200  /*
4201  * Since we don't currently have a way of indicating multiple
4202  * authorization failures, select the first one in the
4203  * bit vector that causes problems.
4204  * Order the switch statement so that its roughly in dependency order
4205  * to result in better error message. The main thing is that
4206  * SELECT should be first.
4207  */
4208 
4209  error = NO_ERROR;
4210  mask = 1;
4211  for (i = 0; i < AU_GRANT_SHIFT && !error; i++)
4212  {
4213  if (requested & mask)
4214  {
4215  /* we asked for this one */
4216  if ((bits & mask) == 0)
4217  {
4218  /* but it wasn't available */
4219  switch (mask)
4220  {
4221  case AU_SELECT:
4222  error = ER_AU_SELECT_FAILURE;
4223  break;
4224  case AU_ALTER:
4225  error = ER_AU_ALTER_FAILURE;
4226  break;
4227  case AU_UPDATE:
4228  error = ER_AU_UPDATE_FAILURE;
4229  break;
4230  case AU_INSERT:
4231  error = ER_AU_INSERT_FAILURE;
4232  break;
4233  case AU_DELETE:
4234  error = ER_AU_DELETE_FAILURE;
4235  break;
4236  case AU_INDEX:
4237  error = ER_AU_INDEX_FAILURE;
4238  break;
4239  case AU_EXECUTE:
4240  error = ER_AU_EXECUTE_FAILURE;
4241  break;
4242  default:
4244  break;
4245  }
4246  }
4247  }
4248  mask = mask << 1;
4249  }
4250 
4251  if (!error)
4252  {
4253  /* we seemed to have all the basic authorizations, check grant options */
4254  mask = 1 << AU_GRANT_SHIFT;
4255  for (i = 0; i < AU_GRANT_SHIFT && !error; i++)
4256  {
4257  if (requested & mask)
4258  {
4259  /* we asked for this one */
4260  if ((bits & mask) == 0)
4261  {
4262  /*
4263  * But it wasn't available, convert this back down to the
4264  * corresponding basic type and select an appropriate error.
4265  *
4266  * NOTE: We need to add type specific errors here !
4267  *
4268  */
4269  atype = mask >> AU_GRANT_SHIFT;
4270  switch (atype)
4271  {
4272  case AU_SELECT:
4273  error = ER_AU_NO_GRANT_OPTION;
4274  break;
4275  case AU_ALTER:
4276  error = ER_AU_NO_GRANT_OPTION;
4277  break;
4278  case AU_UPDATE:
4279  error = ER_AU_NO_GRANT_OPTION;
4280  break;
4281  case AU_INSERT:
4282  error = ER_AU_NO_GRANT_OPTION;
4283  break;
4284  case AU_DELETE:
4285  error = ER_AU_NO_GRANT_OPTION;
4286  break;
4287  case AU_INDEX:
4288  error = ER_AU_NO_GRANT_OPTION;
4289  break;
4290  case AU_EXECUTE:
4291  error = ER_AU_NO_GRANT_OPTION;
4292  break;
4293  default:
4294  error = ER_AU_NO_GRANT_OPTION;
4295  break;
4296  }
4297  }
4298  }
4299  mask = mask << 1;
4300  }
4301  }
4302 
4303  return (error);
4304 }
4305 
4306 /*
4307  * check_grant_option - Checks to see if a class has the grant option for
4308  * a particular authorization type.
4309  * Called by au_grant and au_revoke
4310  * return: error code
4311  * classop(in): MOP of class being examined
4312  * class(in): direct pointer to class structure
4313  * type(in): type of authorization being checked
4314  *
4315  * TODO: LP64
4316  */
4317 static int
4318 check_grant_option (MOP classop, SM_CLASS * sm_class, DB_AUTH type)
4319 {
4320  int error = NO_ERROR;
4321  AU_CLASS_CACHE *cache;
4322  unsigned int cache_bits;
4323  unsigned int mask;
4324 
4325  /*
4326  * this potentially can be called during initialization when we don't
4327  * actually have any users yet. If so, assume its ok
4328  */
4329  if (Au_cache_index < 0)
4330  return NO_ERROR;
4331 
4332  cache = (AU_CLASS_CACHE *) sm_class->auth_cache;
4333  if (sm_class->auth_cache == NULL)
4334  {
4335  cache = au_install_class_cache (sm_class);
4336  if (cache == NULL)
4337  {
4338  assert (er_errid () != NO_ERROR);
4339  return er_errid ();
4340  }
4341  }
4342  cache_bits = cache->data[Au_cache_index];
4343 
4344  if (cache_bits == AU_CACHE_INVALID)
4345  {
4346  if (update_cache (classop, sm_class, cache))
4347  {
4348  assert (er_errid () != NO_ERROR);
4349  return er_errid ();
4350  }
4351  cache_bits = cache->data[Au_cache_index];
4352  }
4353 
4354  /* build the complete bit mask */
4355  mask = type | (type << AU_GRANT_SHIFT);
4356  if ((cache_bits & mask) != mask)
4357  {
4358  error = appropriate_error (cache_bits, mask);
4359  if (error)
4360  {
4362  }
4363  }
4364 
4365  return error;
4366 }
4367 
4368 
4369 /*
4370  * GRANT OPERATION
4371  */
4372 
4373 /*
4374  * au_grant - This is the primary interface function for granting authorization
4375  * on classes.
4376  * return: error code
4377  * user(in): user receiving the grant
4378  * class_mop(in): class being authorized
4379  * type(in): type of authorization
4380  * grant_option(in): non-zero if grant option is also being given
4381  */
4382 int
4383 au_grant (MOP user, MOP class_mop, DB_AUTH type, bool grant_option)
4384 {
4385  int error = NO_ERROR;
4386  MOP auth;
4387  DB_SET *grants;
4388  DB_VALUE value;
4389  int current, save = 0, gindex;
4390  SM_CLASS *classobj;
4391  int is_partition = DB_NOT_PARTITIONED_CLASS, i, savepoint_grant = 0;
4392  MOP *sub_partitions = NULL;
4393 
4394  error = sm_partitioned_class_type (class_mop, &is_partition, NULL, &sub_partitions);
4395  if (error != NO_ERROR)
4396  {
4397  return error;
4398  }
4399 
4400  if (is_partition == DB_PARTITIONED_CLASS)
4401  {
4403  if (error != NO_ERROR)
4404  {
4405  goto fail_end;
4406  }
4407 
4408  savepoint_grant = 1;
4409  for (i = 0; sub_partitions[i]; i++)
4410  {
4411  error = au_grant (user, sub_partitions[i], type, grant_option);
4412  if (error != NO_ERROR)
4413  {
4414  break;
4415  }
4416  }
4417 
4418  free_and_init (sub_partitions);
4419  if (error != NO_ERROR)
4420  {
4421  goto fail_end;
4422  }
4423  }
4424 
4425  AU_DISABLE (save);
4426  if (ws_is_same_object (user, Au_user))
4427  {
4428  /*
4429  * Treat grant to self condition as a success only. Although this
4430  * statement is a no-op, it is not an indication of no-success.
4431  * The "privileges" are indeed already granted to self.
4432  * Note: Revoke from self is an error, because this cannot be done.
4433  */
4434  }
4435  else if ((error = au_fetch_class_force (class_mop, &classobj, AU_FETCH_READ)) == NO_ERROR)
4436  {
4437  if (ws_is_same_object (classobj->owner, user))
4438  {
4439  error = ER_AU_CANT_GRANT_OWNER;
4441  }
4442  else if ((error = check_grant_option (class_mop, classobj, type)) == NO_ERROR)
4443  {
4444  if (au_get_object (user, "authorization", &auth) != NO_ERROR)
4445  {
4446  error = ER_AU_ACCESS_ERROR;
4447  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 2, AU_USER_CLASS_NAME, "authorization");
4448  }
4449  /* lock authorization for write & mark dirty */
4451  {
4452  error = ER_AU_CANT_UPDATE;
4453  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
4454  }
4455  else if ((error = obj_inst_lock (auth, 1)) == NO_ERROR && (error = get_grants (auth, &grants, 1)) == NO_ERROR)
4456  {
4457  gindex = find_grant_entry (grants, class_mop, Au_user);
4458  if (gindex == -1)
4459  {
4460  current = AU_NO_AUTHORIZATION;
4461  }
4462  else
4463  {
4464  /* already granted, get current cache */
4465  error = set_get_element (grants, GRANT_ENTRY_CACHE (gindex), &value);
4466  if (error != NO_ERROR)
4467  {
4468  set_free (grants);
4469  if (sub_partitions)
4470  {
4471  free_and_init (sub_partitions);
4472  }
4473  AU_ENABLE (save);
4474  return (error);
4475  }
4476  current = db_get_int (&value);
4477  }
4478 
4479 #if defined(SA_MODE)
4480  if (catcls_Enable == true)
4481 #endif /* SA_MODE */
4482  {
4483  DB_AUTH ins_bits, upd_bits;
4484 
4485  ins_bits = (DB_AUTH) ((~current & AU_TYPE_MASK) & (int) type);
4486  if (ins_bits)
4487  {
4488  error =
4489  au_insert_new_auth (Au_user, user, class_mop, ins_bits,
4490  (grant_option) ? ins_bits : DB_AUTH_NONE);
4491  }
4492  upd_bits = (DB_AUTH) (~ins_bits & (int) type);
4493  if ((error == NO_ERROR) && upd_bits)
4494  {
4495  error =
4496  au_update_new_auth (Au_user, user, class_mop, upd_bits,
4497  (grant_option) ? upd_bits : DB_AUTH_NONE);
4498  }
4499  }
4500 
4501  /* Fail to insert/update, never change the grant entry set. */
4502  if (error != NO_ERROR)
4503  {
4504  set_free (grants);
4505  goto fail_end;
4506  }
4507 
4508  current |= (int) type;
4509  if (grant_option)
4510  {
4511  current |= ((int) type << AU_GRANT_SHIFT);
4512  }
4513 
4514  db_make_int (&value, current);
4515  if (gindex == -1)
4516  {
4517  /* There is no grant entry, add a new one. */
4518  gindex = add_grant_entry (grants, class_mop, Au_user);
4519  }
4520  set_put_element (grants, GRANT_ENTRY_CACHE (gindex), &value);
4521  set_free (grants);
4522 
4523  /*
4524  * clear the cache for this user/class pair to make sure we
4525  * recalculate it the next time it is referenced
4526  */
4527  reset_cache_for_user_and_class (classobj);
4528 
4529  /*
4530  * Make sure any cached parse trees are rebuild. This proabably
4531  * isn't necessary for GRANT, only REVOKE.
4532  */
4534  }
4535  }
4536  }
4537 
4538 fail_end:
4539  if (savepoint_grant && error != NO_ERROR && error != ER_LK_UNILATERALLY_ABORTED)
4540  {
4542  }
4543  if (sub_partitions)
4544  {
4545  free_and_init (sub_partitions);
4546  }
4547  AU_ENABLE (save);
4548  return (error);
4549 }
4550 
4551 
4552 /*
4553  * REVOKE OPERATION
4554  */
4555 
4556 /*
4557  * free_grant_list - Frees a list of temporary grant flattening structures.
4558  * return: none
4559  * grants(in): list of grant structures
4560  */
4561 static void
4563 {
4564  AU_GRANT *next;
4565 
4566  for (next = NULL; grants != NULL; grants = next)
4567  {
4568  next = grants->next;
4569 
4570  /* always make sure object pointers are NULL in the freed stuff */
4571  grants->auth_object = NULL;
4572  grants->user = NULL;
4573  grants->grantor = NULL;
4574 
4575  db_ws_free (grants);
4576  }
4577 }
4578 
4579 /*
4580  * collect_class_grants - Collects information about every grant of
4581  * a particular type made on a class.
4582  * return: error code
4583  * class_mop(in): class for which we're gathering all grants
4584  * type(in): type of grant we're interested in
4585  * revoked_auth(in): authorization object containing revoked grant
4586  * revoked_grant_index(in): index of revoked grant element
4587  * return_grants(in): returned list of grant structures
4588  *
4589  * Note:
4590  * Since we don't keep the grants associated with the class
4591  * object, we have to visit every user object and collect the grants for
4592  * that class. This could be a lot more effecient if we had a
4593  * "granted to" set in the user object so we can have a more directed
4594  * search.
4595  * The revoked_auth & revoked_grant_index arguments identify a grant
4596  * on some user that is being revoked. When this grant is encountered
4597  * it is not included in the resulting grant list.
4598  * The db_root class used to have a user attribute which was a set
4599  * containing the object-id for all users. The users attribute has been
4600  * eliminated for performance reasons. A query on the db_user class is
4601  * now used to find all users.
4602  */
4603 static int
4604 collect_class_grants (MOP class_mop, DB_AUTH type, MOP revoked_auth, int revoked_grant_index, AU_GRANT ** return_grants)
4605 {
4606  int error = NO_ERROR;
4607  MOP user, auth;
4608  DB_VALUE element;
4609  DB_SET *grants;
4610  AU_GRANT *grant_list, *new_grant;
4611  int cache, j, gsize;
4612  char *query;
4613  size_t query_size;
4614  DB_QUERY_RESULT *query_result;
4615  DB_QUERY_ERROR query_error;
4616  DB_VALUE user_val;
4617  const char *qp1 = "select [%s] from [%s];";
4618 
4619  *return_grants = NULL;
4620 
4621  query_size = strlen (qp1) + strlen (AU_USER_CLASS_NAME) * 2;
4622  query = (char *) malloc (query_size);
4623  if (query == NULL)
4624  {
4626  return ER_OUT_OF_VIRTUAL_MEMORY;
4627  }
4628 
4629  sprintf (query, qp1, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME);
4630  error = db_compile_and_execute_local (query, &query_result, &query_error);
4631  if (error < 0)
4632  /* error is row count if not negative. */
4633  {
4634  free_and_init (query);
4635  return error;
4636  }
4637 
4638  grant_list = NULL;
4639 
4640  while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS)
4641  {
4642  if (db_query_get_tuple_value (query_result, 0, &user_val) == NO_ERROR)
4643  {
4644  if (DB_IS_NULL (&user_val))
4645  {
4646  user = NULL;
4647  }
4648  else
4649  {
4650  user = db_get_object (&user_val);
4651  }
4652 
4653  /* should remove deleted users when encountered ! */
4654  if (au_get_object (user, "authorization", &auth) != NO_ERROR)
4655  {
4656  /* If this is the "deleted object" error, ignore it */
4657  error = er_errid ();
4658  if (error == ER_HEAP_UNKNOWN_OBJECT)
4659  {
4660  error = NO_ERROR;
4661  }
4662  else
4663  {
4664  error = ER_AU_ACCESS_ERROR;
4665  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 2, AU_USER_CLASS_NAME, "authorization");
4666  break;
4667  }
4668  }
4669  else if ((error = get_grants (auth, &grants, 1)) == NO_ERROR)
4670  {
4671 
4672  gsize = set_size (grants);
4673  for (j = 0; j < gsize && error == NO_ERROR; j += GRANT_ENTRY_LENGTH)
4674  {
4675  /* ignore the grant entry that is being revoked */
4676  if (auth == revoked_auth && j == revoked_grant_index)
4677  continue;
4678 
4679  /* see if grant is for the class in question */
4680  if (set_get_element (grants, GRANT_ENTRY_CLASS (j), &element))
4681  {
4682  assert (er_errid () != NO_ERROR);
4683  error = er_errid ();
4684  break;
4685  }
4686 
4687  if (db_get_object (&element) == class_mop)
4688  {
4689  cache = AU_NO_AUTHORIZATION;
4690  if (set_get_element (grants, GRANT_ENTRY_CACHE (j), &element))
4691  {
4692  assert (er_errid () != NO_ERROR);
4693  error = er_errid ();
4694  break;
4695  }
4696 
4697  cache = db_get_int (&element);
4698  if ((cache & (int) type))
4699  {
4700  new_grant = (AU_GRANT *) db_ws_alloc (sizeof (AU_GRANT));
4701  if (new_grant == NULL)
4702  {
4703  assert (er_errid () != NO_ERROR);
4704  error = er_errid ();
4705  break;
4706  }
4707 
4708  new_grant->next = grant_list;
4709  grant_list = new_grant;
4710  new_grant->legal = 0;
4711  new_grant->auth_object = auth;
4712  new_grant->grant_index = j;
4713  new_grant->user = user;
4714  new_grant->grant_option = (((int) type << AU_GRANT_SHIFT) & cache);
4715  if (set_get_element (grants, GRANT_ENTRY_SOURCE (j), &element))
4716  {
4717  assert (er_errid () != NO_ERROR);
4718  error = er_errid ();
4719  }
4720  else
4721  {
4722  if (DB_IS_NULL (&element))
4723  {
4724  new_grant->grantor = NULL;
4725  }
4726  else
4727  {
4728  new_grant->grantor = db_get_object (&element);
4729  }
4730  }
4731  }
4732  }
4733  }
4734  set_free (grants);
4735  }
4736  }
4737  }
4738 
4739  db_query_end (query_result);
4740  free_and_init (query);
4741 
4742  if (error != NO_ERROR && grant_list != NULL)
4743  {
4744  free_grant_list (grant_list);
4745  grant_list = NULL;
4746  }
4747  *return_grants = grant_list;
4748 
4749  return (error);
4750 }
4751 
4752 /*
4753  * map_grant_list - Work function for propagate_revoke.
4754  * return: none
4755  * grants(in): grant list
4756  * grantor(in): owner object
4757  *
4758  * Note: Recursively maps over the elements in a grant list marking all
4759  * grants that have a valid path from the owner.
4760  * If we need to get fancy, this could take timestamp information
4761  * into account.
4762  */
4763 static void
4764 map_grant_list (AU_GRANT * grants, MOP grantor)
4765 {
4766  AU_GRANT *g;
4767 
4768  for (g = grants; g != NULL; g = g->next)
4769  {
4770  if (!g->legal)
4771  {
4772  if (g->grantor == grantor)
4773  {
4774  g->legal = 1;
4775  if (g->grant_option)
4776  {
4777  map_grant_list (grants, g->user);
4778  }
4779  }
4780  }
4781  }
4782 }
4783 
4784 /*
4785  * propagate_revoke - Propagates a revoke operation to all affected users.
4786  * return: error code
4787  * grant_list(in): list of grant nodes
4788  * owner(in): owner of the class
4789  * mask(in): authorization type mask
4790  */
4791 static int
4792 propagate_revoke (AU_GRANT * grant_list, MOP owner, DB_AUTH mask)
4793 {
4794  int error = NO_ERROR;
4795  DB_VALUE element;
4796  DB_SET *grants;
4797  AU_GRANT *g;
4798  int i, length;
4799 
4800  /* determine invalid grants */
4801  map_grant_list (grant_list, owner);
4802 
4803 #if defined(SA_MODE)
4804  if (catcls_Enable == true)
4805 #endif /* SA_MODE */
4806  {
4807  error = au_propagate_del_new_auth (grant_list, mask);
4808  if (error != NO_ERROR)
4809  return error;
4810  }
4811 
4812  /* make sure we can get locks on the affected authorization objects */
4813  for (g = grant_list; g != NULL && error == NO_ERROR; g = g->next)
4814  {
4815  if (!g->legal)
4816  {
4817  /*
4818  * lock authorization for write & mark dirty,
4819  * don't need to pin because we'll be going through the usual
4820  * set interface, this just ensures that the locks can be obtained
4821  */
4823  {
4824  error = ER_AU_CANT_UPDATE;
4825  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
4826  }
4827  }
4828  }
4829 
4830  /* if the locks are available, perform the revoke */
4831  if (error == NO_ERROR)
4832  {
4833  for (g = grant_list; g != NULL && error == NO_ERROR; g = g->next)
4834  {
4835  if (!g->legal)
4836  {
4837  if ((error = obj_inst_lock (g->auth_object, 1)) == NO_ERROR
4838  && (error = get_grants (g->auth_object, &grants, 0)) == NO_ERROR)
4839  {
4840  if ((error = set_get_element (grants, GRANT_ENTRY_CACHE (g->grant_index), &element)) == NO_ERROR)
4841  {
4842  db_make_int (&element, db_get_int (&element) & mask);
4843  error = set_put_element (grants, GRANT_ENTRY_CACHE (g->grant_index), &element);
4844  }
4845  /*
4846  * if cache bits are zero, we can't remove it because
4847  * there may be other entries in the grant list that
4848  * have indexes into this set -
4849  * must wait until all have been processed before
4850  * compressing the set
4851  */
4852  set_free (grants);
4853  }
4854  }
4855  }
4856 
4857  /*
4858  * now go back through and remove any grant entries that have no
4859  * bits set
4860  */
4861  for (g = grant_list; g != NULL && error == NO_ERROR; g = g->next)
4862  {
4863  if (!g->legal)
4864  {
4865  if ((error = obj_inst_lock (g->auth_object, 1)) == NO_ERROR
4866  && (error = get_grants (g->auth_object, &grants, 0)) == NO_ERROR)
4867  {
4868  length = set_size (grants);
4869  for (i = 0; i < length; i += GRANT_ENTRY_LENGTH)
4870  {
4871  if ((error = set_get_element (grants, GRANT_ENTRY_CACHE (i), &element)) != NO_ERROR)
4872  break;
4873  if (db_get_int (&element) == 0)
4874  {
4875  /* remove this entry */
4876  drop_grant_entry (grants, i);
4877  /* must adjust loop termination counter */
4878  length = set_size (grants);
4879  }
4880  }
4881  set_free (grants);
4882  }
4883  }
4884  }
4885  }
4886 
4887  return (error);
4888 }
4889 
4890 /*
4891  * au_revoke - This is the primary interface function for
4892  * revoking authorization
4893  * return: error code
4894  * user(in): user being revoked
4895  * class_mop(in): class being revoked
4896  * type(in): type of authorization being revoked
4897  *
4898  * Note: The authorization of the given type on the given class is removed
4899  * from the authorization info stored with the given user. If this
4900  * user has the grant option for this type and has granted authorization
4901  * to other users, the revoke will be recursively propagated to all
4902  * affected users.
4903  *
4904  * TODO : LP64
4905  */
4906 int
4907 au_revoke (MOP user, MOP class_mop, DB_AUTH type)
4908 {
4909  int error;
4910  MOP auth;
4911  DB_SET *grants = NULL;
4912  DB_VALUE cache_element;
4913  int current, mask, save = 0, gindex;
4914  AU_GRANT *grant_list;
4915  SM_CLASS *classobj;
4916  int is_partition = DB_NOT_PARTITIONED_CLASS, i = 0, savepoint_revoke = 0;
4917  MOP *sub_partitions = NULL;
4918 
4919  error = sm_partitioned_class_type (class_mop, &is_partition, NULL, &sub_partitions);
4920  if (error != NO_ERROR)
4921  {
4922  return error;
4923  }
4924 
4925  if (is_partition == DB_PARTITIONED_CLASS)
4926  {
4928  if (error != NO_ERROR)
4929  {
4930  goto fail_end;
4931  }
4932  savepoint_revoke = 1;
4933 
4934  for (i = 0; sub_partitions[i]; i++)
4935  {
4936  error = au_revoke (user, sub_partitions[i], type);
4937  if (error != NO_ERROR)
4938  {
4939  break;
4940  }
4941  }
4942 
4943  free_and_init (sub_partitions);
4944  if (error != NO_ERROR)
4945  {
4946  goto fail_end;
4947  }
4948  }
4949 
4950  AU_DISABLE (save);
4951  if (ws_is_same_object (user, Au_user))
4952  {
4953  error = ER_AU_CANT_REVOKE_SELF;
4955  goto fail_end;
4956  }
4957 
4958  error = au_fetch_class_force (class_mop, &classobj, AU_FETCH_READ);
4959  if (error == NO_ERROR)
4960  {
4961  if (ws_is_same_object (classobj->owner, user))
4962  {
4963  error = ER_AU_CANT_REVOKE_OWNER;
4965  goto fail_end;
4966  }
4967 
4968  error = check_grant_option (class_mop, classobj, type);
4969  if (error != NO_ERROR)
4970  {
4971  goto fail_end;
4972  }
4973 
4974  if (au_get_object (user, "authorization", &auth) != NO_ERROR)
4975  {
4976  error = ER_AU_ACCESS_ERROR;
4977  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 2, AU_USER_CLASS_NAME, "authorization");
4978  goto fail_end;
4979  }
4981  {
4982  error = ER_AU_CANT_UPDATE;
4983  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
4984  goto fail_end;
4985  }
4986  else if ((error = obj_inst_lock (auth, 1)) == NO_ERROR && (error = get_grants (auth, &grants, 1)) == NO_ERROR)
4987  {
4988  gindex = find_grant_entry (grants, class_mop, Au_user);
4989  if (gindex == -1)
4990  {
4991  error = ER_AU_GRANT_NOT_FOUND;
4993  goto fail_end;
4994  }
4995  else
4996  {
4997  /* get current cache bits */
4998  error = set_get_element (grants, gindex + 2, &cache_element);
4999  if (error != NO_ERROR)
5000  {
5001  set_free (grants);
5002  if (sub_partitions)
5003  {
5004  free_and_init (sub_partitions);
5005  }
5006  AU_ENABLE (save);
5007  return (error);
5008  }
5009  current = db_get_int (&cache_element);
5010 
5011  /*
5012  * If all the bits are set, assume we wan't to
5013  * revoke everything previously granted, makes it a bit
5014  * easier but muddies the semantics too much ?
5015  */
5016  if (type == DB_AUTH_ALL)
5017  {
5018  type = (DB_AUTH) (current & AU_TYPE_MASK);
5019  }
5020 
5021  /*
5022  * this test could be more sophisticated, right now,
5023  * if there are any valid grants that fit in
5024  * the specified bit mask, the operation will proceed,
5025  * we could make sure that every bit in the supplied
5026  * mask is also present in the cache and if not abort
5027  * the whole thing
5028  */
5029 
5030  if ((current & (int) type) == 0)
5031  {
5032  error = ER_AU_GRANT_NOT_FOUND;
5034  }
5035  else if ((error = collect_class_grants (class_mop, type, auth, gindex, &grant_list)) == NO_ERROR)
5036  {
5037 
5038  /* calculate the mask to turn off the grant */
5039  mask = (int) ~(type | (type << AU_GRANT_SHIFT));
5040 
5041  /* propagate the revoke to the affected classes */
5042  if ((error = propagate_revoke (grant_list, classobj->owner, (DB_AUTH) mask)) == NO_ERROR)
5043  {
5044 
5045  /*
5046  * finally, update the local grant for the
5047  * original object
5048  */
5049  current &= mask;
5050  if (current)
5051  {
5052  db_make_int (&cache_element, current);
5053  set_put_element (grants, gindex + 2, &cache_element);
5054  }
5055  else
5056  {
5057  /* no remaining grants, remove it from the grant set */
5058  drop_grant_entry (grants, gindex);
5059  }
5060  /*
5061  * clear the cache for this user/class pair
5062  * to make sure we recalculate it the next time
5063  * it is referenced
5064  */
5065  reset_cache_for_user_and_class (classobj);
5066 
5067 #if defined(SA_MODE)
5068  if (catcls_Enable == true)
5069 #endif /* SA_MODE */
5070  error = au_delete_new_auth (Au_user, user, class_mop, type);
5071 
5072  /*
5073  * Make sure that we don't keep any parse trees
5074  * around that rely on obsolete authorization.
5075  * This may not be necessary.
5076  */
5078  }
5079  free_grant_list (grant_list);
5080  }
5081  }
5082  }
5083  }
5084 
5085 fail_end:
5086  if (grants != NULL)
5087  {
5088  set_free (grants);
5089  }
5090  if (savepoint_revoke && error != NO_ERROR && error != ER_LK_UNILATERALLY_ABORTED)
5091  {
5093  }
5094  if (sub_partitions)
5095  {
5096  free_and_init (sub_partitions);
5097  }
5098  AU_ENABLE (save);
5099  return (error);
5100 }
5101 
5102 /*
5103  * MISC UTILITIES
5104  */
5105 
5106 /*
5107  * au_change_owner - This changes the owning user of a class.
5108  * This should be called only by the DBA.
5109  * return: error code
5110  * classmop(in): class whose owner is to change
5111  * owner(in): new owner
5112  */
5113 int
5114 au_change_owner (MOP classmop, MOP owner)
5115 {
5116  int error = NO_ERROR;
5117  SM_CLASS *class_;
5118  int save;
5119  SM_ATTRIBUTE *attr;
5120 
5121  AU_DISABLE (save);
5122  if (!au_is_dba_group_member (Au_user))
5123  {
5124  error = ER_AU_DBA_ONLY;
5125  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "change_owner");
5126  }
5127  else
5128  {
5129  error = au_fetch_class_force (classmop, &class_, AU_FETCH_UPDATE);
5130  if (error == NO_ERROR)
5131  {
5132  /*
5133  * Change serial object's owner when the class has auto_increment
5134  * attribute column.
5135  */
5136  for (attr = class_->attributes; attr != NULL; attr = (SM_ATTRIBUTE *) attr->header.next)
5137  {
5138  if (attr->auto_increment != NULL)
5139  {
5140  error = au_change_serial_owner (&attr->auto_increment, owner);
5141  if (error != NO_ERROR)
5142  {
5143  goto exit_on_error;
5144  }
5145  }
5146  }
5147 
5148  /* Change class owner */
5149  class_->owner = owner;
5150  error = locator_flush_class (classmop);
5151  }
5152  }
5153 exit_on_error:
5154  AU_ENABLE (save);
5155  return (error);
5156 }
5157 
5158 /*
5159  * au_change_owner_method - Method interface to au_change_owner
5160  * return: none
5161  * obj(in): class whose owner is to change
5162  * returnval(out): return value of this method
5163  * class(in):
5164  * owner(in): new owner
5165  */
5166 void
5167 au_change_owner_method (MOP obj, DB_VALUE * returnval, DB_VALUE * class_, DB_VALUE * owner)
5168 {
5169  MOP user, classmop;
5170  int error = NO_ERROR;
5171  int is_partition = DB_NOT_PARTITIONED_CLASS, i, savepoint_owner = 0;
5172  MOP *sub_partitions = NULL;
5173  const char *class_name = NULL, *owner_name = NULL;
5174  SM_CLASS *clsobj;
5175 
5176  db_make_null (returnval);
5177 
5178  if (DB_IS_NULL (class_) || !IS_STRING (class_) || (class_name = db_get_string (class_)) == NULL)
5179  {
5181  db_make_error (returnval, ER_AU_INVALID_CLASS);
5182  return;
5183  }
5184  if (DB_IS_NULL (owner) || !IS_STRING (owner) || (owner_name = db_get_string (owner)) == NULL)
5185  {
5187  db_make_error (returnval, ER_AU_INVALID_USER);
5188  return;
5189  }
5190 
5191  classmop = sm_find_class (class_name);
5192  if (classmop == NULL)
5193  {
5194  db_make_error (returnval, er_errid ());
5195  return;
5196  }
5197 
5198  error = au_fetch_class_force (classmop, &clsobj, AU_FETCH_UPDATE);
5199  if (error != NO_ERROR)
5200  {
5201  goto fail_return;
5202  }
5203 
5204  /* To change the owner of a system class is not allowed. */
5205  if (sm_issystem (clsobj))
5206  {
5208  db_make_error (returnval, er_errid ());
5209  return;
5210  }
5211 
5212  user = au_find_user (owner_name);
5213  if (user == NULL)
5214  {
5215  db_make_error (returnval, er_errid ());
5216  return;
5217  }
5218 
5219  error = sm_partitioned_class_type (classmop, &is_partition, NULL, &sub_partitions);
5220  if (error != NO_ERROR)
5221  {
5222  goto fail_return;
5223  }
5224 
5225  if (is_partition != DB_NOT_PARTITIONED_CLASS)
5226  {
5227  if (is_partition == DB_PARTITION_CLASS) /* if partition; error */
5228  {
5231  goto fail_return;
5232  }
5233  else /* if partitioned class; do actions to all partitions */
5234  {
5236  if (error != NO_ERROR)
5237  {
5238  goto fail_return;
5239  }
5240  savepoint_owner = 1;
5241  for (i = 0; sub_partitions[i]; i++)
5242  {
5243  error = au_change_owner (sub_partitions[i], user);
5244  if (error != NO_ERROR)
5245  {
5246  break;
5247  }
5248  }
5249  if (error != NO_ERROR)
5250  {
5251  goto fail_return;
5252  }
5253  }
5254  }
5255 
5256  error = au_change_owner (classmop, user);
5257 
5258 fail_return:
5259  if (savepoint_owner && error != NO_ERROR && error != ER_LK_UNILATERALLY_ABORTED)
5260  {
5262  }
5263  if (sub_partitions)
5264  {
5265  free_and_init (sub_partitions);
5266  }
5267  if (error != NO_ERROR)
5268  {
5269  db_make_error (returnval, error);
5270  }
5271 }
5272 
5273 /*
5274  * au_change_serial_owner() - Change serial object's owner
5275  * return: error code
5276  * object(in/out): serial object whose owner is to be changed
5277  * new_owner(in): new owner
5278  */
5279 int
5280 au_change_serial_owner (MOP * object, MOP new_owner)
5281 {
5282  DB_OTMPL *obt_p = NULL;
5283  DB_VALUE value;
5284  int au_save, error;
5285 
5286  assert (object != NULL);
5287 
5288  if (!au_is_dba_group_member (Au_user))
5289  {
5290  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_AU_DBA_ONLY, 1, "change_serial_owner");
5291  return ER_AU_DBA_ONLY;
5292  }
5293 
5294  AU_DISABLE (au_save);
5295 
5296  obt_p = dbt_edit_object (*object);
5297  if (obt_p == NULL)
5298  {
5299  goto exit_on_error;
5300  }
5301 
5302  db_make_object (&value, new_owner);
5303  error = dbt_put_internal (obt_p, "owner", &value);
5304  pr_clear_value (&value);
5305  if (error != NO_ERROR)
5306  {
5307  goto exit_on_error;
5308  }
5309 
5310  *object = dbt_finish_object (obt_p);
5311  if (*object == NULL)
5312  {
5313  goto exit_on_error;
5314  }
5315 
5316  AU_ENABLE (au_save);
5317  return NO_ERROR;
5318 
5319 exit_on_error:
5320  if (obt_p != NULL)
5321  {
5322  dbt_abort_object (obt_p);
5323  }
5324 
5325  AU_ENABLE (au_save);
5326 
5327  assert (er_errid () != NO_ERROR);
5328  return er_errid ();
5329 }
5330 
5331 /*
5332  * au_change_serial_owner_method() - Method interface to au_change_serial_owner
5333  * return: none
5334  * obj(in): class whose owner is to change
5335  * returnval(out): return value of this method
5336  * serial(in): serial name
5337  * owner(in): new owner
5338  */
5339 void
5340 au_change_serial_owner_method (MOP obj, DB_VALUE * returnval, DB_VALUE * serial, DB_VALUE * owner)
5341 {
5342  MOP user = NULL, serial_object = NULL;
5343  MOP serial_class_mop;
5344  DB_IDENTIFIER serial_obj_id;
5345  const char *serial_name = NULL, *owner_name = NULL;
5346  int error = NO_ERROR;
5347 
5348  db_make_null (returnval);
5349 
5350  if (DB_IS_NULL (serial) || !IS_STRING (serial) || (serial_name = db_get_string (serial)) == NULL)
5351  {
5354  return;
5355  }
5356 
5357  if (DB_IS_NULL (owner) || !IS_STRING (owner) || (owner_name = db_get_string (owner)) == NULL)
5358  {
5360  db_make_error (returnval, ER_AU_INVALID_USER);
5361  return;
5362  }
5363 
5364  serial_class_mop = sm_find_class (CT_SERIAL_NAME);
5365 
5366  serial_object = do_get_serial_obj_id (&serial_obj_id, serial_class_mop, serial_name);
5367  if (serial_object == NULL)
5368  {
5371  return;
5372  }
5373 
5374  user = au_find_user (owner_name);
5375  if (user == NULL)
5376  {
5377  db_make_error (returnval, er_errid ());
5378  return;
5379  }
5380 
5381  error = au_change_serial_owner (&serial_object, user);
5382  if (error != NO_ERROR)
5383  {
5384  db_make_error (returnval, error);
5385  }
5386 }
5387 
5388 /*
5389  * au_change_trigger_owner - This changes the owning user of a trigger.
5390  * This should be called only by the DBA.
5391  * return: error code
5392  * trigger(in): trigger whose owner is to change
5393  * owner(in):new owner
5394  */
5395 int
5397 {
5398  int error = NO_ERROR;
5399  int save;
5400  DB_VALUE value;
5401 
5402  AU_DISABLE (save);
5403  if (!au_is_dba_group_member (Au_user))
5404  {
5405  error = ER_AU_DBA_ONLY;
5406  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "change_trigger_owner");
5407  }
5408  else
5409  {
5410  db_make_object (&value, owner);
5411  if ((error = obj_set (trigger, TR_ATT_OWNER, &value)) < 0)
5412  {
5413  goto end;
5414  }
5415  }
5416 
5417 end:
5418  AU_ENABLE (save);
5419  return (error);
5420 }
5421 
5422 /*
5423  * au_change_trigger_owner_method - Method interface to au_change_trigger_owner
5424  * return: none
5425  * obj(in):
5426  * returnval(out): return value of this method
5427  * trigger(in): trigger whose owner is to change
5428  * owner(in): new owner
5429  */
5430 void
5431 au_change_trigger_owner_method (MOP obj, DB_VALUE * returnval, DB_VALUE * trigger, DB_VALUE * owner)
5432 {
5433  MOP user, trigger_mop;
5434  int error;
5435  int ok = 0;
5436 
5437  db_make_null (returnval);
5438  if (trigger != NULL && IS_STRING (trigger) && !DB_IS_NULL (trigger) && db_get_string (trigger) != NULL)
5439  {
5440  if (owner != NULL && IS_STRING (owner) && !DB_IS_NULL (owner) && db_get_string (owner) != NULL)
5441  {
5442 
5443  trigger_mop = tr_find_trigger (db_get_string (trigger));
5444  if (trigger_mop != NULL)
5445  {
5446  user = au_find_user (db_get_string (owner));
5447  if (user != NULL)
5448  {
5449  error = au_change_trigger_owner (trigger_mop, user);
5450  if (error == NO_ERROR)
5451  {
5452  ok = 1;
5453  }
5454  }
5455  }
5456  }
5457  else
5458  {
5460  }
5461  }
5462  else
5463  {
5465  }
5466 
5467  if (!ok)
5468  {
5469  db_make_error (returnval, er_errid ());
5470  }
5471 }
5472 
5473 /*
5474  * au_get_class_owner - This access the user object that is the owner of
5475  * the class.
5476  * return: user object (owner of class_)
5477  * classmop(in): class object
5478  */
5479 MOP
5481 {
5482  MOP owner = NULL;
5483  SM_CLASS *class_;
5484 
5485  /* should we disable authorization here ? */
5486  /*
5487  * should we allow the class owner to be known if the active user doesn't
5488  * have select authorization ?
5489  */
5490 
5491  if (au_fetch_class_force (classmop, &class_, AU_FETCH_READ) == NO_ERROR)
5492  {
5493  owner = class_->owner;
5494  if (owner == NULL)
5495  {
5496  /* shouln't we try to update the class if the owner wasn't set ? */
5497  owner = Au_dba_user;
5498  }
5499  }
5500 
5501  return (owner);
5502 }
5503 
5504 /*
5505  * au_get_owner_method - Method interface to au_change_owner
5506  * return: none
5507  * obj(in):
5508  * returnval(out): return value of this method
5509  * class(in): class object
5510  */
5511 void
5512 au_get_owner_method (MOP obj, DB_VALUE * returnval, DB_VALUE * class_)
5513 {
5514  MOP user;
5515  MOP classmop;
5516  int error = NO_ERROR;
5517 
5518  db_make_null (returnval);
5519  if (class_ != NULL && IS_STRING (class_) && !DB_IS_NULL (class_) && db_get_string (class_) != NULL)
5520  {
5521  classmop = sm_find_class (db_get_string (class_));
5522  if (classmop != NULL)
5523  {
5524  user = au_get_class_owner (classmop);
5525  if (user != NULL)
5526  {
5527  db_make_object (returnval, user);
5528  }
5529  else
5530  {
5531  assert (er_errid () != NO_ERROR);
5532  error = er_errid ();
5533  }
5534  }
5535  else
5536  {
5537  error = ER_AU_INVALID_CLASS;
5538  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, db_get_string (class_));
5539  }
5540  }
5541  else
5542  {
5543  error = ER_AU_INVALID_CLASS;
5544  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
5545  }
5546 
5547  if (error != NO_ERROR)
5548  {
5549  db_make_error (returnval, error);
5550  }
5551 }
5552 
5553 /*
5554  * au_check_authorization_method -
5555  * return: none
5556  * obj(in):
5557  * returnval(out): return value of this method
5558  * class(in):
5559  * auth(in):
5560  */
5561 void
5562 au_check_authorization_method (MOP obj, DB_VALUE * returnval, DB_VALUE * class_, DB_VALUE * auth)
5563 {
5564  MOP classmop;
5565  int error = NO_ERROR;
5566 
5567  db_make_null (returnval);
5568  if (class_ != NULL && IS_STRING (class_) && !DB_IS_NULL (class_) && db_get_string (class_) != NULL)
5569  {
5570 
5571  classmop = sm_find_class (db_get_string (class_));
5572  if (classmop != NULL)
5573  {
5574  error = au_check_authorization (classmop, (DB_AUTH) db_get_int (auth));
5575  db_make_int (returnval, (error == NO_ERROR) ? true : false);
5576  }
5577  else
5578  {
5579  error = ER_AU_INVALID_CLASS;
5580  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, db_get_string (class_));
5581  }
5582  }
5583  else
5584  {
5585  error = ER_AU_INVALID_CLASS;
5586  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
5587  }
5588 }
5589 
5590 /*
5591  * au_add_method_check_authorization -
5592  * return: error code
5593  */
5594 int
5596 {
5597  MOP auth;
5598  SM_TEMPLATE *def;
5599  int save;
5600 
5601  AU_DISABLE (save);
5602 
5604  if (auth == NULL)
5605  {
5606  goto exit_on_error;
5607  }
5608 
5609  def = smt_edit_class_mop (auth, AU_ALTER);
5610  if (def == NULL)
5611  {
5612  goto exit_on_error;
5613  }
5614 
5615  smt_add_class_method (def, "check_authorization", "au_check_authorization_method");
5616  smt_assign_argument_domain (def, "check_authorization", true, NULL, 0, "integer", (DB_DOMAIN *) 0);
5617  smt_assign_argument_domain (def, "check_authorization", true, NULL, 1, "varchar(255)", (DB_DOMAIN *) 0);
5618  smt_assign_argument_domain (def, "check_authorization", true, NULL, 2, "integer", (DB_DOMAIN *) 0);
5619  sm_update_class (def, NULL);
5620 
5621  au_grant (Au_public_user, auth, AU_EXECUTE, false);
5622 
5623  AU_ENABLE (save);
5624  return NO_ERROR;
5625 
5626 exit_on_error:
5627  AU_ENABLE (save);
5628  return ER_FAILED;
5629 }
5630 
5631 /*
5632  * au_change_sp_owner -
5633  * return: error code
5634  * sp(in):
5635  * owner(in):
5636  */
5637 int
5639 {
5640  int error = NO_ERROR;
5641  int save;
5642  DB_VALUE value;
5643 
5644  AU_DISABLE (save);
5645  if (!au_is_dba_group_member (Au_user))
5646  {
5647  error = ER_AU_DBA_ONLY;
5648  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "change_sp_owner");
5649  }
5650  else
5651  {
5652  db_make_object (&value, owner);
5653  error = obj_set (sp, SP_ATTR_OWNER, &value);
5654  if (error < 0)
5655  {
5656  goto end;
5657  }
5658  }
5659 
5660 end:
5661  AU_ENABLE (save);
5662  return (error);
5663 }
5664 
5665 /*
5666  * au_change_sp_owner_method -
5667  * return: none
5668  * obj(in):
5669  * returnval(in):
5670  * sp(in):
5671  * owner(in):
5672  */
5673 void
5674 au_change_sp_owner_method (MOP obj, DB_VALUE * returnval, DB_VALUE * sp, DB_VALUE * owner)
5675 {
5676  MOP user, sp_mop;
5677  int error;
5678  int ok = 0;
5679 
5680  db_make_null (returnval);
5681  if (sp != NULL && IS_STRING (sp) && !DB_IS_NULL (sp) && db_get_string (sp) != NULL)
5682  {
5683  if (owner != NULL && IS_STRING (owner) && !DB_IS_NULL (owner) && db_get_string (owner) != NULL)
5684  {
5685  sp_mop = jsp_find_stored_procedure (db_get_string (sp));
5686  if (sp_mop != NULL)
5687  {
5688  user = au_find_user (db_get_string (owner));
5689  if (user != NULL)
5690  {
5691  error = au_change_sp_owner (sp_mop, user);
5692  if (error == NO_ERROR)
5693  {
5694  ok = 1;
5695  }
5696  }
5697  }
5698  }
5699  else
5700  {
5702  }
5703  }
5704  else
5705  {
5707  }
5708 
5709  if (!ok)
5710  {
5711  db_make_error (returnval, er_errid ());
5712  }
5713 }
5714 
5715 /*
5716  * au_check_user - This is used to check for a currently valid user for some
5717  * operations that are not strictly based on
5718  * any particular class.
5719  * return: error code
5720  */
5721 int
5723 {
5724  int error = NO_ERROR;
5725 
5726  if (Au_user == NULL)
5727  {
5728  error = ER_AU_INVALID_USER;
5729  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
5730  }
5731 
5732  return (error);
5733 }
5734 
5735 /*
5736  * au_user_name - Returns the name of the current user, the string must be
5737  * freed with ws_free_string (db_string_free).
5738  * return: user name (NULL if error)
5739  *
5740  * Note: Note that this is what should always be used to get the active user.
5741  * Au_user_name is only used as a temporary storage area during login.
5742  * Once the database is open, the active user is determined by Au_user
5743  * and Au_user_name doesn't necessarily track this.
5744  */
5745 const char *
5747 {
5748  DB_VALUE value;
5749  const char *name = NULL;
5750 
5751  if (Au_user == NULL)
5752  {
5753  /*
5754  * Database hasn't been started yet, return the registered name
5755  * if any.
5756  */
5757  if (strlen (Au_user_name) == 0)
5758  {
5760  }
5761  else
5762  {
5763  name = ws_copy_string (Au_user_name);
5764  /*
5765  * When this function is called before the workspace memory
5766  * manager was not initialized in the case of client
5767  * initialization(db_restart()), ws_copy_string() will return
5768  * NULL.
5769  */
5770  }
5771  }
5772  else
5773  {
5774  int save;
5775 
5776  AU_DISABLE (save);
5777 
5778  if (obj_get (Au_user, "name", &value) == NO_ERROR)
5779  {
5780  if (!IS_STRING (&value))
5781  {
5783  pr_clear_value (&value);
5784  }
5785  else if (DB_IS_NULL (&value))
5786  {
5787  name = NULL;
5788  }
5789  else
5790  {
5791  name = db_get_string (&value);
5792  name = ws_copy_string (name);
5793  pr_clear_value (&value);
5794  }
5795  }
5796 
5797  AU_ENABLE (save);
5798  }
5799 
5800  return name;
5801 }
5802 
5803 bool
5805 {
5806  return Au_user != NULL || strlen (Au_user_name) > 0;
5807 }
5808 
5809 /*
5810  * CLASS ACCESSING
5811  */
5812 
5813 /*
5814  * is_protected_class - This is a hack to detect attempts to modify one
5815  * of the protected system classes.
5816  * return: non-zero if class is protected
5817  * classmop(in): class MOP
5818  * class(in): class structure
5819  * auth(in): authorization type
5820  *
5821  * Note: This is necessary because normally when DBA is logged in,
5822  * authorization is effectively disabled.
5823  * This should be handled by another "system" level of authorization.
5824  */
5825 static int
5826 is_protected_class (MOP classmop, SM_CLASS * sm_class, DB_AUTH auth)
5827 {
5828  int illegal = 0;
5829 
5830  if (classmop == Au_authorizations_class || IS_CATALOG_CLASS (sm_ch_name ((MOBJ) sm_class)))
5831  {
5832  illegal = auth & (AU_ALTER | AU_DELETE | AU_INSERT | AU_UPDATE | AU_INDEX);
5833  }
5834  else if (sm_issystem (sm_class))
5835  {
5836  /* if the class is a system class_, can't alter */
5837  illegal = auth & (AU_ALTER);
5838  }
5839  return illegal;
5840 }
5841 
5842 /*
5843  * check_authorization - This is the core routine for checking authorization
5844  * on a class.
5845  * return: error code
5846  * classobj(in): class MOP
5847  * class(in): class structure
5848  * type(in): authorization type
5849  *
5850  * TODO : LP64
5851  */
5852 static int
5853 check_authorization (MOP classobj, SM_CLASS * sm_class, DB_AUTH type)
5854 {
5855  int error = NO_ERROR;
5856  AU_CLASS_CACHE *cache;
5857  unsigned int bits;
5858 
5859  /*
5860  * Callers generally check Au_disable already to avoid the function call.
5861  * Check it again to be safe, at this point, it isn't going to add anything.
5862  */
5863  if (Au_disable)
5864  {
5865  return NO_ERROR;
5866  }
5867 
5868  /* try to catch attempts by even the DBA to update a protected class */
5869  if ((sm_class->flags & SM_CLASSFLAG_SYSTEM) && is_protected_class (classobj, sm_class, type))
5870  {
5871  error = appropriate_error (0, type);
5873  }
5874  else
5875  {
5876  cache = (AU_CLASS_CACHE *) sm_class->auth_cache;
5877  if (cache == NULL)
5878  {
5879  cache = au_install_class_cache (sm_class);
5880  if (cache == NULL)
5881  {
5882  assert (er_errid () != NO_ERROR);
5883  return er_errid ();
5884  }
5885  }
5886  bits = cache->data[Au_cache_index];
5887 
5888  if ((bits & type) != type)
5889  {
5890  if (bits == AU_CACHE_INVALID)
5891  {
5892  /* update the cache and try again */
5893  error = update_cache (classobj, sm_class, cache);
5894  if (error == NO_ERROR)
5895  {
5896  bits = cache->data[Au_cache_index];
5897  if ((bits & type) != type)
5898  {
5899  error = appropriate_error (bits, type);
5901  }
5902  }
5903  }
5904  else
5905  {
5906  error = appropriate_error (bits, type);
5908  }
5909  }
5910  }
5911 
5912  return error;
5913 }
5914 
5915 /*
5916  * fetch_class - Work function for au_fetch_class.
5917  * return: error code
5918  * op(in): class or instance MOP
5919  * return_mop(out): returned class MOP
5920  * return_class(out): returned class structure
5921  * fetchmode(in): desired fetch/locking mode
5922  */
5923 static int
5924 fetch_class (MOP op, MOP * return_mop, SM_CLASS ** return_class, AU_FETCHMODE fetchmode, FETCH_BY fetch_by)
5925 {
5926  int error = NO_ERROR;
5927  MOP classmop = NULL;
5928  SM_CLASS *class_ = NULL;
5929 
5930  *return_mop = NULL;
5931  *return_class = NULL;
5932 
5933  if (op == NULL)
5934  {
5935  return ER_FAILED;
5936  }
5937 
5938  classmop = NULL;
5939  class_ = NULL;
5940 
5941  if (fetch_by == BY_CLASS_MOP)
5942  {
5943  /* already know classmop */
5944  classmop = op;
5945  }
5946  else
5947  {
5948  int is_class;
5949  DB_FETCH_MODE purpose;
5950 
5951  if (fetchmode == AU_FETCH_READ)
5952  {
5953  purpose = DB_FETCH_READ;
5954  }
5955  else
5956  {
5957  purpose = DB_FETCH_WRITE;
5958  }
5959 
5960  is_class = locator_is_class (op, purpose);
5961 
5962  if (is_class < 0)
5963  {
5964  return is_class;
5965  }
5966  else if (is_class > 0)
5967  {
5968  classmop = op;
5969  }
5970  else
5971  {
5972  classmop = ws_class_mop (op);
5973  }
5974  }
5975 
5976  /* the locator_fetch_class_of_instance doesn't seem to be working right now */
5977 #if 0
5978  if (classmop == NULL)
5979  {
5980  if ((error = classmop_from_instance (op, &classmop)) != NO_ERROR)
5981  return (error);
5982  }
5983 #endif /* 0 */
5984 
5985  if (classmop != NULL)
5986  {
5987  switch (fetchmode)
5988  {
5989  case AU_FETCH_READ:
5990  class_ = (SM_CLASS *) locator_fetch_class (classmop, DB_FETCH_READ);
5991  break;
5992  case AU_FETCH_SCAN:
5993  class_ = (SM_CLASS *) locator_fetch_class (classmop, DB_FETCH_SCAN);
5994  break;
5996  class_ = (SM_CLASS *) locator_fetch_class (classmop, DB_FETCH_EXCLUSIVE_SCAN);
5997  break;
5998  case AU_FETCH_WRITE:
5999  class_ = (SM_CLASS *) locator_fetch_class (classmop, DB_FETCH_WRITE);
6000  break;
6001  case AU_FETCH_UPDATE:
6002  class_ = (SM_CLASS *) locator_update_class (classmop);
6003  break;
6004  }
6005  }
6006  else
6007  {
6008  switch (fetchmode)
6009  {
6010  case AU_FETCH_READ:
6011  class_ = (SM_CLASS *) locator_fetch_class_of_instance (op, &classmop, DB_FETCH_READ);
6012  break;
6013  case AU_FETCH_SCAN:
6015  /* AU_FETCH_SCAN, AU_FETCH_EXCLUSIVE_SCAN are allowed only for class mops. */
6016  assert (0);
6017  break;
6018  case AU_FETCH_WRITE:
6019  class_ = (SM_CLASS *) locator_fetch_class_of_instance (op, &classmop, DB_FETCH_WRITE);
6020  break;
6021  case AU_FETCH_UPDATE:
6022  class_ = (SM_CLASS *) locator_fetch_class_of_instance (op, &classmop, DB_FETCH_WRITE);
6023  if (class_ != NULL)
6024  {
6025  /*
6026  * all this appreciably does is set the dirty flag in the MOP
6027  * should have the "dirty after getting write lock" operation
6028  * separated
6029  */
6030  class_ = (SM_CLASS *) locator_update_class (classmop);
6031  }
6032  break;
6033  }
6034  }
6035 
6036  /* I've seen cases where locator_fetch has an error but doesn't return NULL ?? */
6037  /* this is debug only, take out in production */
6038  /*
6039  * if (class_ != NULL && Db_error != NO_ERROR)
6040  * au_log(Db_error, "Inconsistent error handling ?");
6041  */
6042 
6043  if (class_ == NULL)
6044  {
6045  /* does it make sense to check WS_IS_DELETED here ? */
6046  error = er_errid ();
6047  /* !!! do we need to mask the error here ? */
6048 
6049  /*
6050  * if the object was deleted, set the workspace bit so we can avoid this
6051  * in the future
6052  */
6053  if (error == ER_HEAP_UNKNOWN_OBJECT)
6054  {
6055  if (classmop != NULL)
6056  {
6057  WS_SET_DELETED (classmop);
6058  }
6059  else
6060  {
6061  WS_SET_DELETED (op);
6062  }
6063  }
6064  else if (error == NO_ERROR)
6065  {
6066  /* return NO_ERROR only if class_ is not null. */
6067  error = ER_FAILED;
6068  }
6069  }
6070  else
6071  {
6072  *return_mop = classmop;
6073  *return_class = class_;
6074  }
6075 
6076  return error;
6077 }
6078 
6079 /*
6080  * au_fetch_class_internal - helper function for au_fetch_class families
6081  * return: error code
6082  * op(in): class or instance
6083  * class_ptr(out): returned pointer to class structure
6084  * fetchmode(in): type of fetch/lock to obtain
6085  * type(in): authorization type to check
6086  * fetch_by(in): DONT_KNOW, BY_INSTANCE_MOP or BY_CLASS_MOP
6087  */
6088 int
6090 {
6091  int error = NO_ERROR;
6092  SM_CLASS *class_;
6093  MOP classmop;
6094 
6095  if (class_ptr != NULL)
6096  {
6097  *class_ptr = NULL;
6098  }
6099 
6100  if (op == NULL)
6101  {
6103  return ER_OBJ_INVALID_ARGUMENTS;
6104  }
6105 
6106  if (Au_user == NULL && !Au_disable)
6107  {
6108  error = ER_AU_INVALID_USER;
6109  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
6110  return error;
6111  }
6112 
6113  if (fetchmode != AU_FETCH_READ /* not just reading */
6114  || WS_IS_DELETED (op) /* marked deleted */
6115  || op->object == NULL /* never been fetched */
6116  || op->class_mop != sm_Root_class_mop /* not a class */
6117  || op->lock < SCH_S_LOCK) /* don't have the lowest level lock */
6118  {
6119  /* go through the usual fetch process */
6120  error = fetch_class (op, &classmop, &class_, fetchmode, fetch_by);
6121  if (error != NO_ERROR)
6122  {
6123  return error;
6124  }
6125  }
6126  else
6127  {
6128  /* looks like a basic read fetch, check authorization only */
6129  classmop = op;
6130  class_ = (SM_CLASS *) op->object;
6131  }
6132 
6133  /* check class representation directory */
6134  if (OID_ISNULL (sm_ch_rep_dir ((MOBJ) class_)))
6135  {
6136  if (!locator_is_root (classmop))
6137  {
6138  error = sm_check_catalog_rep_dir (classmop, class_);
6139  if (error != NO_ERROR)
6140  {
6141  return error;
6142  }
6143 
6144 #if !defined(NDEBUG)
6145  if (!OID_ISTEMP (WS_OID (classmop)))
6146  {
6147  assert (!OID_ISNULL (sm_ch_rep_dir ((MOBJ) class_)));
6148  }
6149 #endif
6150  }
6151  }
6152 
6153  if (Au_disable || !(error = check_authorization (classmop, class_, type)))
6154  {
6155  if (class_ptr != NULL)
6156  {
6157  *class_ptr = class_;
6158  }
6159  }
6160 
6161  return error;
6162 }
6163 
6164 /*
6165  * au_fetch_class - This is the primary function for accessing a class
6166  * return: error code
6167  * op(in): class or instance
6168  * class_ptr(out): returned pointer to class structure
6169  * fetchmode(in): type of fetch/lock to obtain
6170  * type(in): authorization type to check
6171  *
6172  */
6173 int
6174 au_fetch_class (MOP op, SM_CLASS ** class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
6175 {
6176  return au_fetch_class_internal (op, class_ptr, fetchmode, type, DONT_KNOW);
6177 }
6178 
6179 /*
6180  * au_fetch_class_by_classmop - This is the primary function
6181  * for accessing a class by an instance mop.
6182  * return: error code
6183  * op(in): class or instance
6184  * class_ptr(out): returned pointer to class structure
6185  * fetchmode(in): type of fetch/lock to obtain
6186  * type(in): authorization type to check
6187  *
6188  */
6189 int
6191 {
6192  return au_fetch_class_internal (op, class_ptr, fetchmode, type, BY_INSTANCE_MOP);
6193 }
6194 
6195 /*
6196  * au_fetch_class_by_classmop - This is the primary function
6197  * for accessing a class by a class mop.
6198  * return: error code
6199  * op(in): class or instance
6200  * class_ptr(out): returned pointer to class structure
6201  * fetchmode(in): type of fetch/lock to obtain
6202  * type(in): authorization type to check
6203  *
6204  */
6205 int
6206 au_fetch_class_by_classmop (MOP op, SM_CLASS ** class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
6207 {
6208  return au_fetch_class_internal (op, class_ptr, fetchmode, type, BY_CLASS_MOP);
6209 }
6210 
6211 /*
6212  * au_fetch_class_force - This is like au_fetch_class except that it will
6213  * not check for authorization.
6214  * return: error code
6215  * op(in): class or instance MOP
6216  * class(out): returned pointer to class structure
6217  * fetchmode(in): desired operation
6218  *
6219  * Note: Used in a few special cases where authorization checking is
6220  * to be disabled.
6221  */
6222 int
6223 au_fetch_class_force (MOP op, SM_CLASS ** class_, AU_FETCHMODE fetchmode)
6224 {
6225  MOP classmop;
6226 
6227  return (fetch_class (op, &classmop, class_, fetchmode, DONT_KNOW));
6228 }
6229 
6230 /*
6231  * au_check_authorization - This is similar to au_fetch_class except that
6232  * it only checks for available authorization and
6233  * doesn't actually return the fetched class
6234  * return: error code
6235  * op(in): class object
6236  * auth(in): authorization type biits
6237  *
6238  * Note: Where it differs most is that it doesn't check the Au_disable flag.
6239  * This means that it can be used when authorization
6240  * is temporarily disabled to get the true status for a class.
6241  * This is important for modules like the trigger manager that often
6242  * run with authorization disabled but which need to verify access
6243  * rights for the current user.
6244  */
6245 int
6247 {
6248  int error = NO_ERROR;
6249  SM_CLASS *class_;
6250  int save;
6251 
6252  /*
6253  * It seems to be simplest to just override the Au_disable
6254  * flag and call au_fetch_class normally. If this turns
6255  * out to be a problem, will have to duplicate some of
6256  * au_fetch_class here.
6257  */
6258 
6259  save = Au_disable;
6260  Au_disable = 0;
6261  error = au_fetch_class (op, &class_, AU_FETCH_READ, auth);
6262  Au_disable = save;
6263 
6264  return error;
6265 }
6266 
6267 
6268 /*
6269  * INSTANCE ACCESSING
6270  */
6271 
6272 /*
6273  * fetch_instance - Work function for au_fetch_instance.
6274  * return: error code
6275  * op(in): instance MOP
6276  * obj_ptr(out): returned pointer to object
6277  * fetchmode(in): desired operation
6278  * fetch_version_type(in): fetch version type, currently used in case of
6279  * read/write fetch
6280  */
6281 static int
6282 fetch_instance (MOP op, MOBJ * obj_ptr, AU_FETCHMODE fetchmode, LC_FETCH_VERSION_TYPE fetch_version_type)
6283 {
6284  int error = NO_ERROR;
6285  MOBJ obj = NULL;
6286  int pin;
6287  int save;
6288 
6289  if (obj_ptr != NULL)
6290  {
6291  *obj_ptr = NULL;
6292  }
6293 
6294  if (op == NULL)
6295  {
6297  return ER_OBJ_INVALID_ARGUMENTS;
6298  }
6299 
6300  /* refuse attempts to fetch temporary objects */
6301  if (op->is_temp)
6302  {
6304  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6305  return error;
6306  }
6307 
6308  /* DO NOT PUT ANY RETURNS FROM HERE UNTIL THE AU_ENABLE */
6309  AU_DISABLE (save);
6310 
6311  pin = ws_pin (op, 1);
6312  if (op->is_vid)
6313  {
6314  switch (fetchmode)
6315  {
6316  case AU_FETCH_READ:
6317  obj = vid_fetch_instance (op, DB_FETCH_READ, fetch_version_type);
6318  break;
6319  case AU_FETCH_WRITE:
6320  obj = vid_fetch_instance (op, DB_FETCH_WRITE, fetch_version_type);
6321  break;
6322  case AU_FETCH_UPDATE:
6323  obj = vid_upd_instance (op);
6324  break;
6325  case AU_FETCH_SCAN:
6328  assert (0);
6329  break;
6330  }
6331  }
6332  else
6333  {
6334  switch (fetchmode)
6335  {
6336  case AU_FETCH_READ:
6337  obj = locator_fetch_instance (op, DB_FETCH_READ, fetch_version_type);
6338  break;
6339  case AU_FETCH_WRITE:
6340  obj = locator_fetch_instance (op, DB_FETCH_WRITE, fetch_version_type);
6341  break;
6342  case AU_FETCH_UPDATE:
6343  obj = locator_update_instance (op);
6344  break;
6345  case AU_FETCH_SCAN:
6348  assert (0);
6349  break;
6350  }
6351  }
6352 
6353  (void) ws_pin (op, pin);
6354 
6355  if (obj == NULL)
6356  {
6357  /* does it make sense to check WS_IS_DELETED here ? */
6358  assert (er_errid () != NO_ERROR);
6359  error = er_errid ();
6360 
6361  /*
6362  * if the object was deleted, set the workspace bit so we can avoid this
6363  * in the future
6364  */
6365  if (error == ER_HEAP_UNKNOWN_OBJECT)
6366  {
6367  WS_SET_DELETED (op);
6368  }
6369  else if (error == NO_ERROR)
6370  {
6371  /* return NO_ERROR only if obj is not null. */
6372  error = ER_FAILED;
6373  }
6374  }
6375  else if (obj_ptr != NULL)
6376  {
6377  *obj_ptr = obj;
6378  }
6379 
6380  AU_ENABLE (save);
6381 
6382  return error;
6383 }
6384 
6385 /*
6386  * au_fetch_instance - This is the primary interface function for accessing
6387  * an instance.
6388  * return: error code
6389  * op(in): instance MOP
6390  * obj_ptr(in):returned pointer to instance memory
6391  * mode(in): access type
6392  * type(in): authorization type
6393  * fetch_version_type(in): fetch version type
6394  *
6395  * Note: Fetch the object from the database if necessary, update the class
6396  * authorization cache if necessary and check authorization for the
6397  * desired operation.
6398  *
6399  * Note: If op is a VMOP au_fetch_instance will return set obj_ptr as a
6400  * pointer to the BASE INSTANCE memory which is not the instance
6401  * associated with op. Therefore, the object returned is not necessarily
6402  * the contents of the supplied MOP.
6403  */
6404 /*
6405  * TODO We need to carefully examine all callers of au_fetch_instance and make
6406  * sure they know that the object returned is not necessarily the
6407  * contents of the supplied MOP.
6408  */
6409 int
6410 au_fetch_instance (MOP op, MOBJ * obj_ptr, AU_FETCHMODE mode, LC_FETCH_VERSION_TYPE fetch_version_type, DB_AUTH type)
6411 {
6412  int error = NO_ERROR;
6413  SM_CLASS *class_;
6414  MOP classmop;
6415 
6416  if (Au_user == NULL && !Au_disable)
6417  {
6418  error = ER_AU_INVALID_USER;
6419  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
6420  return error;
6421  }
6422 
6423  error = fetch_class (op, &classmop, &class_, AU_FETCH_READ, BY_INSTANCE_MOP);
6424  if (error != NO_ERROR)
6425  {
6426  /*
6427  * the class was deleted, make sure the instance MOP also gets
6428  * the deleted bit set so the upper levels can depend on this
6429  * behavior
6430  */
6431  if (error == ER_HEAP_UNKNOWN_OBJECT)
6432  {
6433  WS_SET_DELETED (op);
6434  }
6435  return error;
6436  }
6437 
6438  if (Au_disable || !(error = check_authorization (classmop, class_, type)))
6439  {
6440  error = fetch_instance (op, obj_ptr, mode, fetch_version_type);
6441  }
6442 
6443  return error;
6444 }
6445 
6446 /*
6447  * au_fetch_instance_force - Like au_fetch_instance but doesn't check
6448  * for authorization. Used in special circumstances
6449  * when authorization is disabled.
6450  * return: error code
6451  * op(in): instance MOP
6452  * obj_ptr(out): returned instance memory pointer
6453  * fetchmode(in): access type
6454  * fetch_version_type(in): fetch version type
6455  */
6456 int
6457 au_fetch_instance_force (MOP op, MOBJ * obj_ptr, AU_FETCHMODE fetchmode, LC_FETCH_VERSION_TYPE fetch_version_type)
6458 {
6459  return (fetch_instance (op, obj_ptr, fetchmode, fetch_version_type));
6460 }
6461 
6462 
6463 /*
6464  * LOGIN/LOGOUT
6465  */
6466 
6467 /*
6468  * au_disable_passwords -
6469  * return: none
6470  */
6471 void
6473 {
6474  Au_ignore_passwords = 1;
6475 }
6476 
6477 /*
6478  * au_set_user -
6479  * return: error code
6480  * newuser(in):
6481  */
6482 int
6483 au_set_user (MOP newuser)
6484 {
6485  int error = NO_ERROR;
6486  int index;
6487 
6488  if (newuser != NULL && !ws_is_same_object (newuser, Au_user))
6489  {
6490  if (!(error = au_find_user_cache_index (newuser, &index, 1)))
6491  {
6492 
6493  Au_user = newuser;
6495 
6496  /*
6497  * it is important that we don't call sm_bump_local_schema_version() here
6498  * because this function is called during the compilation of vclasses
6499  */
6500 
6501  /*
6502  * Entry-level SQL specifies that the schema name is the same as
6503  * the current user authorization name. In any case, this is
6504  * the place to set the current schema since the user just changed.
6505  */
6506  error = sc_set_current_schema (Au_user);
6507  }
6508  }
6509  return (error);
6510 }
6511 
6512 /*
6513  * au_perform_login - This changes the current user using the supplied
6514  * name & password.
6515  * return: error code
6516  * name(in): user name
6517  * password(in): user password
6518  *
6519  * Note: It is called both by au_login() and au_start().
6520  * Once the name/password have been validated, it calls au_set_user()
6521  * to set the user object and calculate the authorization cache index.
6522  * Assumes authorization has been disabled.
6523  */
6524 static int
6525 au_perform_login (const char *name, const char *password, bool ignore_dba_privilege)
6526 {
6527  int error = NO_ERROR;
6528  MOP user;
6529  DB_VALUE value;
6530  const char *pass;
6531  char *dbuser = NULL, *dbpassword = NULL;
6532 
6533  dbuser = (char *) name;
6534  dbpassword = (char *) password;
6535 
6536  if (dbuser == NULL || strlen (dbuser) == 0)
6537  {
6538  error = ER_AU_NO_USER_LOGGED_IN;
6540  }
6541  else
6542  {
6543  Au_public_user = au_find_user (AU_PUBLIC_USER_NAME);
6544  Au_dba_user = au_find_user (AU_DBA_USER_NAME);
6545  if (Au_public_user == NULL || Au_dba_user == NULL)
6546  {
6547  error = er_errid ();
6548  if (error != ER_LK_UNILATERALLY_ABORTED)
6549  {
6550  error = ER_AU_INCOMPLETE_AUTH;
6551  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6552  }
6553  }
6554  user = au_find_user (dbuser);
6555  if (user == NULL)
6556  {
6557  error = er_errid ();
6558  if (error != ER_LK_UNILATERALLY_ABORTED)
6559  {
6560  error = ER_AU_INVALID_USER;
6561  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, dbuser);
6562  }
6563  }
6564  else
6565  {
6566  if (obj_get (user, "password", &value) != NO_ERROR)
6567  {
6568  error = ER_AU_CORRUPTED;
6569  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6570  }
6571  else
6572  {
6573  /*
6574  * hack, allow password checking to be turned off in certain
6575  * cases, like the utility programs that will always run in DBA
6576  * mode but don't want to have to enter a password, also
6577  * if a sucessful DBA login ocurred, allow users to be
6578  * changed without entering passwords
6579  */
6580 
6581  if (!Au_ignore_passwords && (!au_is_dba_group_member (Au_user) || ignore_dba_privilege))
6582  {
6583  pass = NULL;
6584  if (!DB_IS_NULL (&value) && db_get_object (&value) != NULL)
6585  {
6586  if (obj_get (db_get_object (&value), "password", &value))
6587  {
6588  assert (er_errid () != NO_ERROR);
6589  return er_errid ();
6590  }
6591  if (IS_STRING (&value))
6592  {
6593  if (DB_IS_NULL (&value))
6594  {
6595  pass = NULL;
6596  }
6597  else
6598  {
6599  pass = db_get_string (&value);
6600  }
6601  }
6602  }
6603 
6604  if (pass != NULL && strlen (pass))
6605  {
6606  /* the password is present and must match */
6607  if ((dbpassword == NULL) || (strlen (dbpassword) == 0)
6608  || !match_password (dbpassword, db_get_string (&value)))
6609  {
6610  error = ER_AU_INVALID_PASSWORD;
6612  }
6613  }
6614  else
6615  {
6616  /*
6617  * the password in the user object is effectively NULL,
6618  * only accept the login if the user supplied an empty
6619  * password.
6620  * Formerly any password string was accepted
6621  * if the stored password was NULL which is
6622  * not quite right.
6623  */
6624  if (dbpassword != NULL && strlen (dbpassword))
6625  {
6626  error = ER_AU_INVALID_PASSWORD;
6628  }
6629  }
6630  if (pass != NULL)
6631  {
6632  ws_free_string (db_get_string (&value));
6633  }
6634  }
6635 
6636  if (error == NO_ERROR)
6637  {
6638  error = AU_SET_USER (user);
6639 
6640  /* necessary to invalidate vclass cache */
6642  }
6643  }
6644  }
6645  }
6646  return (error);
6647 }
6648 
6649 /*
6650  * au_login - Registers a user name and password for a database.
6651  * return: error code
6652  * name(in): user name
6653  * password(in): password
6654  * ignore_dba_privilege(in) : whether ignore DBA's privilege or not in login
6655  *
6656  * Note: If a database has already been restarted, the user will be validated
6657  * immediately, otherwise the name and password are simply saved
6658  * in global variables and the validation will ocurr the next time
6659  * bo_restart is called.
6660  */
6661 int
6662 au_login (const char *name, const char *password, bool ignore_dba_privilege)
6663 {
6664  int error = NO_ERROR;
6665  int save;
6666 
6667  /*
6668  * because the database can be left open after authorization failure,
6669  * checking Au_root for NULL isn't a reliable way to see of the database
6670  * is in an "un-restarted" state. Instead, look at BOOT_IS_CLIENT_RESTARTED
6671  * which is defined to return non-zero if a valid transaction is in
6672  * progress.
6673  */
6674  if (Au_root == NULL || !BOOT_IS_CLIENT_RESTARTED ())
6675  {
6676  /*
6677  * Save the name & password for later. Allow the name to be NULL
6678  * and leave it unmodified.
6679  */
6680  if (name != NULL)
6681  {
6682  if (strlen (name) >= DB_MAX_USER_LENGTH)
6683  {
6684  error = ER_USER_NAME_TOO_LONG;
6685  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6686  return error;
6687  }
6688  strcpy (Au_user_name, name);
6689  }
6690 
6691  if (password == NULL || strlen (password) == 0)
6692  {
6693  strcpy (Au_user_password_des_oldstyle, "");
6694  strcpy (Au_user_password_sha1, "");
6695  strcpy (Au_user_password_sha2_512, "");
6696  }
6697  else
6698  {
6699  /* store the password encrypted(DES and SHA1 both) so we don't have buffers lying around with the obvious
6700  * passwords in it. */
6704  }
6705  }
6706  else
6707  {
6708  /* Change users within an active database. */
6709  AU_DISABLE (save);
6710  error = au_perform_login (name, password, ignore_dba_privilege);
6711  AU_ENABLE (save);
6712  }
6713  return (error);
6714 }
6715 
6716 /*
6717  * au_login_method - Method interface to au_login.
6718  * return: none
6719  * class_mop(in): class object
6720  * returnval(out): return value of this method
6721  * user(in): user name
6722  * password(in): password
6723  */
6724 void
6725 au_login_method (MOP class_mop, DB_VALUE * returnval, DB_VALUE * user, DB_VALUE * password)
6726 {
6727  int error = NO_ERROR;
6728  char *user_name;
6729 
6730  if (user != NULL)
6731  {
6732  if (IS_STRING (user) && !DB_IS_NULL (user) && db_get_string (user) != NULL)
6733  {
6734  if (password != NULL && IS_STRING (password))
6735  {
6736  error = au_login (db_get_string (user), db_get_string (password), false);
6737  }
6738  else
6739  {
6740  error = au_login (db_get_string (user), NULL, false);
6741  }
6742  }
6743  }
6744  else
6745  {
6746  error = ER_AU_INVALID_USER;
6747  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
6748  }
6749 
6750  if (error == NO_ERROR)
6751  {
6752  user_name = db_get_user_name ();
6753  error = clogin_user (user_name);
6754 
6755  if (error == NO_ERROR)
6756  {
6757  db_make_null (returnval);
6758  }
6759  else
6760  {
6761  db_make_error (returnval, error);
6762  }
6763 
6764  db_string_free (user_name);
6765  }
6766  else
6767  {
6768  db_make_error (returnval, error);
6769  }
6770 }
6771 
6772 /*
6773  * au_start - This is called during the bo_resteart initialization sequence
6774  * after the database has been successfully opened
6775  * return: error code
6776  *
6777  * Note: Here we initialize the authorization system by finding the system
6778  * objects and validating the registered user.
6779  */
6780 int
6781 au_start (void)
6782 {
6783  int error = NO_ERROR;
6784  MOPLIST mops;
6785  MOP class_mop;
6786 
6787  /*
6788  * NEED TO MAKE SURE THIS IS 1 IF THE SERVER CRASHED BECAUSE WE'RE
6789  * GOING TO CALL db_ FUNCTIONS
6790  */
6792 
6793  /*
6794  * It is important not to enable authorization until after the
6795  * login is finished, otherwise the system will stop when it tries
6796  * to validate the user when accessing the authorization objects.
6797  */
6798  Au_disable = 1;
6799 
6800  /* locate the various system classes */
6801  class_mop = sm_find_class (AU_ROOT_CLASS_NAME);
6802  if (class_mop == NULL)
6803  {
6804  error = ER_AU_NO_AUTHORIZATION;
6805  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6806  return (error);
6807  }
6808  Au_authorizations_class = class_mop;
6809 
6810  class_mop = sm_find_class (AU_AUTH_CLASS_NAME);
6811  if (class_mop == NULL)
6812  {
6813  error = ER_AU_NO_AUTHORIZATION;
6814  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6815  return (error);
6816  }
6817  Au_authorization_class = class_mop;
6818 
6819  class_mop = sm_find_class (AU_USER_CLASS_NAME);
6820  if (class_mop == NULL)
6821  {
6822  error = ER_AU_NO_AUTHORIZATION;
6823  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6824  return (error);
6825  }
6826  Au_user_class = class_mop;
6827 
6828  class_mop = sm_find_class (AU_PASSWORD_CLASS_NAME);
6829  if (class_mop == NULL)
6830  {
6831  error = ER_AU_NO_AUTHORIZATION;
6832  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6833  return (error);
6834  }
6835  Au_password_class = class_mop;
6836 
6837  mops = db_get_all_objects (Au_authorizations_class);
6838  if (mops == NULL)
6839  {
6840  error = ER_AU_NO_AUTHORIZATION;
6841  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6842  }
6843  else
6844  {
6845  /* this shouldn't happen, not sure what to do */
6846  if (mops->next != NULL)
6847  {
6848  error = ER_AU_MULTIPLE_ROOTS;
6849  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6850  }
6851 
6852  Au_root = mops->op;
6853  db_objlist_free (mops);
6854 
6855  Au_public_user = au_find_user (AU_PUBLIC_USER_NAME);
6856  Au_dba_user = au_find_user (AU_DBA_USER_NAME);
6857  if (Au_public_user == NULL || Au_dba_user == NULL)
6858  {
6859  error = er_errid ();
6860  if (error != ER_LK_UNILATERALLY_ABORTED)
6861  {
6862  error = ER_AU_INCOMPLETE_AUTH;
6863  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6864  }
6865  }
6866  else
6867  {
6868  /*
6869  * If you try to start the authorization system and
6870  * there is no user logged in, you will automatically be logged in
6871  * as "PUBLIC". Optionally, we could get a name from the
6872  * cubrid.conf file or use the name of the current Unix user.
6873  */
6874  if (strlen (Au_user_name) == 0)
6875  {
6876  strcpy (Au_user_name, "PUBLIC");
6877  }
6878 
6880  }
6881  }
6882 
6883  /* make sure this is off */
6884  Au_disable = 0;
6885 
6886  return (error);
6887 }
6888 
6889 
6890 /*
6891  * MIGRATION SUPPORT
6892  *
6893  * These functions provide a way to dump the authorization catalog
6894  * as a sequence of CSQL statements. When the statements are evaluated
6895  * by the interpreter, it will reconstruct the authorization catalog.
6896  */
6897 
6898 /*
6899  * au_get_user_name - Shorthand function for getting name from user object.
6900  * Must remember to free the string
6901  * return: user name string
6902  * obj(in): user object
6903  */
6904 char *
6906 {
6907  DB_VALUE value;
6908  db_make_null (&value);
6909  char *name = NULL;
6910 
6911  int error = obj_get (obj, "name", &value);
6912  if (error == NO_ERROR)
6913  {
6914  if (IS_STRING (&value) && !DB_IS_NULL (&value) && db_get_string (&value) != NULL)
6915  {
6916  name = ws_copy_string (db_get_string (&value));
6917  }
6918  }
6919 
6920  db_value_clear (&value);
6921 
6922  return name;
6923 }
6924 
6925 
6926 /*
6927  * au_export_users - Generates a sequence of add_user and add_member method
6928  * calls that when evaluated, will re-create the current
6929  * user/group hierarchy.
6930  * return: error code
6931  * output_ctx(in/out): print context
6932  */
6933 int
6935 {
6936  int error;
6937  DB_SET *direct_groups = NULL;
6938  DB_VALUE value, gvalue;
6939  MOP user = NULL, pwd = NULL;
6940  int g, gcard;
6941  const char *uname = NULL, *str = NULL, *gname = NULL, *comment = NULL;
6942  char passbuf[AU_MAX_PASSWORD_BUF];
6943  char *query = NULL;
6944  size_t query_size;
6945  DB_QUERY_RESULT *query_result;
6946  DB_QUERY_ERROR query_error;
6947  DB_VALUE user_val;
6948  const char *qp1 = "select [%s] from [%s];";
6949  char encrypt_mode = 0x00;
6950 
6951  query_size = strlen (qp1) + strlen (AU_USER_CLASS_NAME) * 2;
6952  query = (char *) malloc (query_size);
6953  if (query == NULL)
6954  {
6956  return ER_OUT_OF_VIRTUAL_MEMORY;
6957  }
6958 
6959  sprintf (query, qp1, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME);
6960 
6961  error = db_compile_and_execute_local (query, &query_result, &query_error);
6962  /* error is row count if not negative. */
6963  if (error < 0)
6964  {
6965  free_and_init (query);
6966  return error;
6967  }
6968 
6969  while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS)
6970  {
6971  if (db_query_get_tuple_value (query_result, 0, &user_val) != NO_ERROR)
6972  {
6973  continue;
6974  }
6975 
6976  if (DB_IS_NULL (&user_val))
6977  {
6978  user = NULL;
6979  }
6980  else
6981  {
6982  user = db_get_object (&user_val);
6983  }
6984 
6985  uname = au_get_user_name (user);
6986  strcpy (passbuf, "");
6987  encrypt_mode = 0x00;
6988 
6989  /* retrieve password */
6990  error = obj_get (user, "password", &value);
6991  if (error == NO_ERROR)
6992  {
6993  if (DB_IS_NULL (&value))
6994  {
6995  pwd = NULL;
6996  }
6997  else
6998  {
6999  pwd = db_get_object (&value);
7000  }
7001 
7002  if (pwd != NULL)
7003  {
7004  error = obj_get (pwd, "password", &value);
7005  if (error == NO_ERROR)
7006  {
7007  if (!DB_IS_NULL (&value) && DB_IS_STRING (&value))
7008  {
7009  /*
7010  * copy password string using malloc
7011  * to be consistent with encrypt_password
7012  */
7013  str = db_get_string (&value);
7014  if (IS_ENCODED_DES (str))
7015  {
7016  /* strip off the prefix so its readable */
7017  snprintf (passbuf, AU_MAX_PASSWORD_BUF - 1, "%s", str + 1);
7018  encrypt_mode = ENCODE_PREFIX_DES;
7019  }
7020  else if (IS_ENCODED_SHA1 (str))
7021  {
7022  /* strip off the prefix so its readable */
7023  snprintf (passbuf, AU_MAX_PASSWORD_BUF - 1, "%s", str + 1);
7024  encrypt_mode = ENCODE_PREFIX_SHA1;
7025  }
7026  else if (IS_ENCODED_SHA2_512 (str))
7027  {
7028  /* not strip off the prefix */
7029  snprintf (passbuf, AU_MAX_PASSWORD_BUF - 1, "%s", str);
7030  encrypt_mode = ENCODE_PREFIX_SHA2_512;
7031  }
7032  else if (strlen (str))
7033  {
7034  /* sha2 hashing with prefix */
7035  encrypt_password_sha2_512 (str, passbuf);
7036  }
7037  ws_free_string (str);
7038  }
7039  }
7040  }
7041  }
7042 
7043  /* retrieve comment */
7044  error = obj_get (user, "comment", &value);
7045  if (error == NO_ERROR)
7046  {
7047  if (DB_IS_NULL (&value))
7048  {
7049  comment = NULL;
7050  }
7051  else
7052  {
7053  comment = db_get_string (&value);
7054  }
7055  }
7056 
7057  if (error == NO_ERROR)
7058  {
7059  if (!ws_is_same_object (user, Au_dba_user) && !ws_is_same_object (user, Au_public_user))
7060  {
7061  if (!strlen (passbuf))
7062  {
7063  output_ctx ("call [add_user]('%s', '') on class [db_root];\n", uname);
7064  }
7065  else
7066  {
7067  output_ctx ("call [add_user]('%s', '') on class [db_root] to [auser];\n", uname);
7068  if (encrypt_mode == ENCODE_PREFIX_DES)
7069  {
7070  output_ctx ("call [set_password_encoded]('%s') on [auser];\n", passbuf);
7071  }
7072  else
7073  {
7074  output_ctx ("call [set_password_encoded_sha1]('%s') on [auser];\n", passbuf);
7075  }
7076  }
7077  }
7078  else
7079  {
7080  if (strlen (passbuf))
7081  {
7082  output_ctx ("call [find_user]('%s') on class [db_user] to [auser];\n", uname);
7083  if (encrypt_mode == ENCODE_PREFIX_DES)
7084  {
7085  output_ctx ("call [set_password_encoded]('%s') on [auser];\n", passbuf);
7086  }
7087  else
7088  {
7089  output_ctx ("call [set_password_encoded_sha1]('%s') on [auser];\n", passbuf);
7090  }
7091  }
7092  }
7093 
7094  /* export comment */
7095  if (comment != NULL && comment[0] != '\0')
7096  {
7097  output_ctx ("ALTER USER [%s] ", uname);
7098  help_print_describe_comment (output_ctx, comment);
7099  output_ctx (";\n");
7100  }
7101  }
7102 
7103  /* remember, these were allocated in the workspace */
7104  if (uname != NULL)
7105  {
7106  ws_free_string (uname);
7107  }
7108  if (comment != NULL)
7109  {
7110  ws_free_string (comment);
7111  }
7112  }
7113 
7114  /* group hierarchy */
7115  if (db_query_first_tuple (query_result) == DB_CURSOR_SUCCESS)
7116  {
7117  output_ctx ("call [find_user]('PUBLIC') on class [db_user] to [g_public];\n");
7118  do
7119  {
7120  if (db_query_get_tuple_value (query_result, 0, &user_val) != NO_ERROR)
7121  {
7122  continue;
7123  }
7124 
7125  if (DB_IS_NULL (&user_val))
7126  {
7127  user = NULL;
7128  }
7129  else
7130  {
7131  user = db_get_object (&user_val);
7132  }
7133 
7134  uname = au_get_user_name (user);
7135  if (uname == NULL)
7136  {
7137  continue;
7138  }
7139 
7140  if (au_get_set (user, "direct_groups", &direct_groups) != NO_ERROR)
7141  {
7142  ws_free_string (uname);
7143  continue;
7144  }
7145 
7146  gcard = set_cardinality (direct_groups);
7147  for (g = 0; g < gcard && !error; g++)
7148  {
7149  if (set_get_element (direct_groups, g, &gvalue) != NO_ERROR)
7150  {
7151  continue;
7152  }
7153 
7154  if (ws_is_same_object (db_get_object (&gvalue), Au_public_user))
7155  {
7156  continue;
7157  }
7158 
7159  error = obj_get (db_get_object (&gvalue), "name", &value);
7160  if (error != NO_ERROR)
7161  {
7162  continue;
7163  }
7164 
7165  if (DB_IS_NULL (&value))
7166  {
7167  gname = NULL;
7168  }
7169  else
7170  {
7171  gname = db_get_string (&value);
7172  }
7173 
7174  if (gname != NULL)
7175  {
7176  output_ctx ("call [find_user]('%s') on class [db_user] to [g_%s];\n", gname, gname);
7177  output_ctx ("call [add_member]('%s') on [g_%s];\n", uname, gname);
7178  ws_free_string (gname);
7179  }
7180  }
7181 
7182  set_free (direct_groups);
7183  ws_free_string (uname);
7184  }
7185  while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS);
7186  }
7187 
7188  db_query_end (query_result);
7189  free_and_init (query);
7190 
7191  return (error);
7192 }
7193 
7194 /*
7195  * GRANT EXPORT
7196  *
7197  * This is in support of the authorization migration utilities. We build
7198  * hierarchy of grant information and then generate a sequence of
7199  * CSQL statemenets to recreate the grants. Note that the grants have
7200  * to be done in order of dependencies.
7201  */
7202 
7203 /*
7204  * make_class_grant - Create a temporary class grant structure.
7205  * return: new class grant
7206  * user(in): subject user
7207  * cache(in): authorization bits to grant
7208  */
7209 static CLASS_GRANT *
7210 make_class_grant (CLASS_USER * user, int cache)
7211 {
7212  CLASS_GRANT *grant;
7213 
7214  if ((grant = (CLASS_GRANT *) malloc (sizeof (CLASS_GRANT))) != NULL)
7215  {
7216  grant->next = NULL;
7217  grant->user = user;
7218  grant->cache = cache;
7219  }
7220  return (grant);
7221 }
7222 
7223 /*
7224  * make_class_user - Create a temporary class user structure.
7225  * return: new class user structure
7226  * user_obj(in): pointer to actual database object for this user
7227  */
7228 static CLASS_USER *
7230 {
7231  CLASS_USER *u;
7232 
7233  if ((u = (CLASS_USER *) malloc (sizeof (CLASS_USER))) != NULL)
7234  {
7235  u->next = NULL;
7236  u->obj = user_obj;
7237  u->grants = NULL;
7238 
7239  /*
7240  * This authorization of this user class structure would normally
7241  * be filled in by examining authorizations granted by other users.
7242  * The DBA user is special in that it should have full authorization
7243  * without being granted it by any users. Therefore we need to set
7244  * the authorization explicitly before any code checks it.
7245  */
7246  if (ws_is_same_object (user_obj, Au_dba_user))
7247  {
7249  }
7250  else
7251  {
7252  u->available_auth = 0;
7253  }
7254  }
7255  return (u);
7256 }
7257 
7258 /*
7259  * free_class_grants - Frees list of temporary class grant structures.
7260  * return: none
7261  * grants(in): list of class grant structures
7262  */
7263 static void
7265 {
7266  CLASS_GRANT *g, *next;
7267 
7268  for (g = grants, next = NULL; g != NULL; g = next)
7269  {
7270  next = g->next;
7271  free_and_init (g);
7272  }
7273 }
7274 
7275 /*
7276  * free_class_users - Frees list of class user objects.
7277  * return: none
7278  * users(in): class user list
7279  */
7280 static void
7282 {
7283  CLASS_USER *u, *next;
7284 
7285  for (u = users, next = NULL; u != NULL; u = next)
7286  {
7287  next = u->next;
7289  free_and_init (u);
7290  }
7291 }
7292 
7293 /*
7294  * find_or_add_user - Adds an entry in the user list of a class authorization
7295  * structure for the user object.
7296  * return: class user structures
7297  * auth(in):class authorization state
7298  * user_obj(in):database user object to add
7299  *
7300  * Note: If there is already an entry in the list, it returns the found entry
7301  */
7302 static CLASS_USER *
7303 find_or_add_user (CLASS_AUTH * auth, MOP user_obj)
7304 {
7305  CLASS_USER *u, *last;
7306 
7307  for (u = auth->users, last = NULL; u != NULL && !ws_is_same_object (u->obj, user_obj); u = u->next)
7308  {
7309  last = u;
7310  }
7311 
7312  if (u == NULL)
7313  {
7314  u = make_class_user (user_obj);
7315  if (last == NULL)
7316  {
7317  auth->users = u;
7318  }
7319  else
7320  {
7321  last->next = u;
7322  }
7323  }
7324  return (u);
7325 }
7326 
7327 /*
7328  * add_class_grant - Makes an entry in the class authorization state
7329  * for a desired grant.
7330  * return: error code
7331  * auth(in): class authorization state
7332  * source(in): source user object
7333  * user(in): subject user object
7334  * cache(in): authorization cache bits
7335  */
7336 static int
7337 add_class_grant (CLASS_AUTH * auth, MOP source, MOP user, int cache)
7338 {
7339  CLASS_USER *u, *gu;
7340  CLASS_GRANT *g;
7341 
7342  u = find_or_add_user (auth, source);
7343 
7344  for (g = u->grants; g != NULL && !ws_is_same_object (g->user->obj, user); g = g->next)
7345  ;
7346 
7347  if (g == NULL)
7348  {
7349  if (!ws_is_same_object (source, user))
7350  {
7351  gu = find_or_add_user (auth, user);
7352  g = make_class_grant (gu, cache);
7353  if (g == NULL)
7354  {
7355  assert (er_errid () != NO_ERROR);
7356  return er_errid ();
7357  }
7358  g->next = u->grants;
7359  u->grants = g;
7360  }
7361  }
7362  else
7363  {
7364  /*
7365  * this shouldn't happen, multiple grants from source should already have
7366  * been combined
7367  */
7368  g->cache |= cache;
7369  }
7370  return NO_ERROR;
7371 }
7372 
7373 /*
7374  * build_class_grant_list - Adds grant entries in cl_auth for every grant entry
7375  * found in the authorization catalog for
7376  * the class "class".
7377  * return: error code
7378  * cl_auth(in): class authorization state
7379  * class(in): class object
7380  *
7381  * Note: The db_root class used to have a user attribute which was a set
7382  * containing the object-id for all users. The users attribute has been
7383  * eliminated for performance reasons. A query on the db_user class is
7384  * now used to find all users.
7385  */
7386 static int
7387 build_class_grant_list (CLASS_AUTH * cl_auth, MOP class_mop)
7388 {
7389  int error;
7390  MOP user, auth, source;
7391  DB_SET *grants;
7392  DB_VALUE value;
7393  int j, gsize, cache;
7394  char *query;
7395  size_t query_size;
7396  DB_QUERY_RESULT *query_result;
7397  DB_QUERY_ERROR query_error;
7398  DB_VALUE user_val;
7399  const char *qp1 = "select [%s] from [%s];";
7400 
7401  query_size = strlen (qp1) + strlen (AU_USER_CLASS_NAME) * 2;
7402  query = (char *) malloc (query_size);
7403  if (query == NULL)
7404  {
7406  return ER_OUT_OF_VIRTUAL_MEMORY;
7407  }
7408 
7409  sprintf (query, qp1, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME);
7410 
7411  error = db_compile_and_execute_local (query, &query_result, &query_error);
7412  if (error < 0)
7413  /* error is row count if not negative. */
7414  {
7415  free_and_init (query);
7416  return error;
7417  }
7418 
7419  while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS)
7420  {
7421  if (db_query_get_tuple_value (query_result, 0, &user_val) == NO_ERROR)
7422  {
7423  if (DB_IS_NULL (&user_val))
7424  {
7425  user = NULL;
7426  }
7427  else
7428  {
7429  user = db_get_object (&user_val);
7430  }
7431 
7432  error = au_get_object (user, "authorization", &auth);
7433  /* ignore the deleted object errors */
7434  if (error != NO_ERROR)
7435  {
7436  if (error == ER_HEAP_UNKNOWN_OBJECT)
7437  error = NO_ERROR;
7438  }
7439  else
7440  {
7441  if ((error = get_grants (auth, &grants, 1)) == NO_ERROR)
7442  {
7443  gsize = set_size (grants);
7444  for (j = 0; j < gsize; j += GRANT_ENTRY_LENGTH)
7445  {
7446  error = set_get_element (grants, GRANT_ENTRY_CLASS (j), &value);
7447  if (error == NO_ERROR && DB_VALUE_TYPE (&value) == DB_TYPE_OBJECT
7448  && db_get_object (&value) == class_mop)
7449  {
7450  error = set_get_element (grants, GRANT_ENTRY_SOURCE (j), &value);
7451  if (error == NO_ERROR && DB_VALUE_TYPE (&value) == DB_TYPE_OBJECT && !DB_IS_NULL (&value)
7452  && (source = db_get_object (&value)) != NULL)
7453  {
7454  error = set_get_element (grants, GRANT_ENTRY_CACHE (j), &value);
7455  if (error == NO_ERROR)
7456  {
7457  cache = db_get_int (&value);
7458  error = add_class_grant (cl_auth, source, user, cache);
7459  }
7460  }
7461  }
7462  }
7463  set_free (grants);
7464  }
7465  }
7466  } /* if */
7467  } /* while */
7468 
7469  db_query_end (query_result);
7470  free_and_init (query);
7471 
7472  return (error);
7473 }
7474 
7475 
7476 /*
7477  * issue_grant_statement - Generates an CSQL "grant" statement.
7478  * return: none
7479  * output_ctx(in/out): output context
7480  * auth(in): class authorization state
7481  * grant(in): desired grant
7482  * authbits(in): specific authorization to grant
7483  * quoted_id_flag(in):
7484  */
7485 static void
7486 issue_grant_statement (print_output & output_ctx, CLASS_AUTH * auth, CLASS_GRANT * grant, int authbits)
7487 {
7488  const char *gtype, *classname;
7489  char *username;
7490  int typebit;
7491 
7492  typebit = authbits & AU_TYPE_MASK;
7493  switch (typebit)
7494  {
7495  case AU_SELECT:
7496  gtype = "SELECT";
7497  break;
7498  case AU_INSERT:
7499  gtype = "INSERT";
7500  break;
7501  case AU_UPDATE:
7502  gtype = "UPDATE";
7503  break;
7504  case AU_DELETE:
7505  gtype = "DELETE";
7506  break;
7507  case AU_ALTER:
7508  gtype = "ALTER";
7509  break;
7510  case AU_INDEX:
7511  gtype = "INDEX";
7512  break;
7513  case AU_EXECUTE:
7514  gtype = "EXECUTE";
7515  break;
7516  default:
7517  gtype = "???";
7518  break;
7519  }
7520  classname = sm_get_ch_name (auth->class_mop);
7521  username = au_get_user_name (grant->user->obj);
7522 
7523  output_ctx ("GRANT %s ON ", gtype);
7524  output_ctx ("[%s]", classname);
7525 
7526  if (username != NULL)
7527  {
7528  output_ctx (" TO [%s]", username);
7529  }
7530  else
7531  {
7532  output_ctx (" TO %s", "???");
7533  }
7534 
7535  if (authbits & (typebit << AU_GRANT_SHIFT))
7536  {
7537  output_ctx (" WITH GRANT OPTION");
7538  }
7539  output_ctx (";\n");
7540 
7541  ws_free_string (username);
7542 }
7543 
7544 
7545 /*
7546  * class_grant_loop - Makes a pass on the authorization user list and
7547  * issues grant statements for any users that are able.
7548  * Returns the number of statements issued
7549  * return: number of statements issued
7550  * output_ctx(in): output context
7551  * auth(in): class authorization state
7552  * quoted_id_flag(in):
7553  *
7554  * Note:
7555  * If this resturns zero and the user list is not empty, it indicates
7556  * that there are illegal grants in the hierarchy that were not rooted
7557  * in the class owner object.
7558  *
7559  * It would likely be more efficient if rather than making a full pass
7560  * on the list we evaluate the first node in the list and then recursively
7561  * evaluate every mode affected by the first evaluation. If the first
7562  * node results in no evaluations, we move to the next node in the list.
7563  *
7564  * This will tend to get grants to come out "depth first" which may be
7565  * more logical when examining the resulting statements. It will probably
7566  * result in fewer traversals of the user list as well ?
7567  *
7568  * TODO : LP64
7569  */
7570 static int
7572 {
7573 #define AU_MIN_BIT 1 /* AU_SELECT */
7574 #define AU_MAX_BIT 0x40 /* AU_EXECUTE */
7575 
7576  CLASS_USER *user;
7577  CLASS_GRANT *grant, *prev_grant, *next_grant;
7578  int statements = 0;
7579  int mask, authbits;
7580 
7581  for (user = auth->users; user != NULL; user = user->next)
7582  {
7583  for (grant = user->grants, prev_grant = NULL, next_grant = NULL; grant != NULL; grant = next_grant)
7584  {
7585  next_grant = grant->next;
7586  mask = AU_SELECT;
7587  for (mask = AU_MIN_BIT; mask <= AU_MAX_BIT; mask = mask << 1)
7588  {
7589  if (grant->cache & mask)
7590  {
7591  /* combine auth type & grant option bit */
7592  authbits = mask | (grant->cache & (mask << AU_GRANT_SHIFT));
7593  /*
7594  * if the user has these same bits available,
7595  * issue the grant
7596  */
7597  if ((user->available_auth & authbits) == authbits)
7598  {
7599  issue_grant_statement (output_ctx, auth, grant, authbits);
7600  /* turn on grant bits in the granted user */
7601  grant->user->available_auth |= authbits;
7602  /* turn off the pending grant bits in granting user */
7603  grant->cache &= ~authbits;
7604  statements++;
7605  }
7606  }
7607  }
7608  if (grant->cache == 0)
7609  {
7610  /* no more grants, remove it from the list */
7611  if (prev_grant == NULL)
7612  {
7613  user->grants = grant->next;
7614  }
7615  else
7616  {
7617  prev_grant->next = grant->next;
7618  }
7619  grant->next = NULL;
7620  free_class_grants (grant);
7621  }
7622  else
7623  {
7624  prev_grant = grant;
7625  }
7626  }
7627  /*
7628  * could remove user from the list but can't free it because
7629  * structure may be referenced by a grant inside another user
7630  */
7631  }
7632  return (statements);
7633 }
7634 
7635 
7636 /*
7637  * au_export_grants() - Issues a sequence of CSQL grant statements related
7638  * to the given class.
7639  * return: error code
7640  * output_ctx(in): output context
7641  * class_mop(in): class of interest
7642  * quoted_id_flag(in):
7643  */
7644 int
7645 au_export_grants (print_output & output_ctx, MOP class_mop)
7646 {
7647  int error = NO_ERROR;
7648  CLASS_AUTH cl_auth;
7649  CLASS_USER *u;
7650  int statements, ecount;
7651  char *uname;
7652 
7653  cl_auth.class_mop = class_mop;
7654  cl_auth.owner = au_get_class_owner (class_mop);
7655  cl_auth.users = NULL;
7656 
7657  /* make an entry for the owner with complete authorization */
7658  u = find_or_add_user (&cl_auth, cl_auth.owner);
7660 
7661  /* add entries for the other users with authorization on this class */
7662  error = build_class_grant_list (&cl_auth, class_mop);
7663  if (error == NO_ERROR)
7664  {
7665  /* loop through the grant list, issuing grant statements */
7666  while ((statements = class_grant_loop (output_ctx, &cl_auth)))
7667  ;
7668 
7669  for (u = cl_auth.users, ecount = 0; u != NULL; u = u->next)
7670  {
7671  if (u->grants != NULL)
7672  {
7673  uname = au_get_user_name (u->obj);
7674 
7675  /*
7676  * should this be setting an error condition ?
7677  * for now, leave a comment in the output file
7678  */
7679  output_ctx ("/*");
7682  output_ctx ("*/\n");
7683  ws_free_string (uname);
7684  ecount++;
7685  }
7686  }
7687  if (ecount)
7688  {
7689  error = ER_GENERIC_ERROR;
7690  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
7691  }
7692  }
7693 
7694  free_class_users (cl_auth.users);
7695 
7696  return (error);
7697 }
7698 
7699 /*
7700  * DEBUGGING FUNCTIONS
7701  */
7702 
7703 /*
7704  * au_print_cache() -
7705  * return: none
7706  * cache(in):
7707  * fp(in):
7708  */
7709 static void
7710 au_print_cache (int cache, FILE * fp)
7711 {
7712  int i, mask, auth, option;
7713 
7714  if (cache < 0)
7715  {
7717  }
7718  else
7719  {
7720  for (i = 0; i < 7; i++)
7721  {
7722  mask = 1 << i;
7723  auth = cache & mask;
7724  option = cache & (mask << AU_GRANT_SHIFT);
7725  if (option)
7726  fprintf (fp, "*");
7727  if (auth)
7728  fprintf (fp, "%s ", auth_type_name[i]);
7729  }
7730  }
7731  fprintf (fp, "\n");
7732 }
7733 
7734 /*
7735  * au_print_grant_entry() -
7736  * return: none
7737  * grants(in):
7738  * grant_index(in):
7739  * fp(in):
7740  */
7741 static void
7742 au_print_grant_entry (DB_SET * grants, int grant_index, FILE * fp)
7743 {
7744  DB_VALUE value;
7745 
7746  set_get_element (grants, GRANT_ENTRY_CLASS (grant_index), &value);
7748  sm_get_ch_name (db_get_object (&value)));
7749  fprintf (fp, " ");
7750 
7751  set_get_element (grants, GRANT_ENTRY_SOURCE (grant_index), &value);
7752  obj_get (db_get_object (&value), "name", &value);
7753 
7755  db_get_string (&value));
7756 
7757  pr_clear_value (&value);
7758 
7759  set_get_element (grants, GRANT_ENTRY_CACHE (grant_index), &value);
7760  au_print_cache (db_get_int (&value), fp);
7761 }
7762 
7763 /*
7764  * au_print_auth() -
7765  * return: none
7766  * auth(in):
7767  * fp(in):
7768  */
7769 static void
7770 au_print_auth (MOP auth, FILE * fp)
7771 {
7772  DB_VALUE value;
7773  DB_SET *grants;
7774  int i, gsize;
7775  int error;
7776 
7777  /* kludge, some older databases used the name "user", rather than "owner" */
7778  error = obj_get (auth, "owner", &value);
7779  if (error != NO_ERROR)
7780  {
7781  error = obj_get (auth, "user", &value);
7782  if (error != NO_ERROR)
7783  return; /* punt */
7784  }
7785 
7786  if (db_get_object (&value) != NULL)
7787  {
7788  obj_get (db_get_object (&value), "name", &value);
7790  db_get_string (&value));
7791  pr_clear_value (&value);
7792  }
7793  else
7794  {
7796  }
7797 
7798  get_grants (auth, &grants, 1);
7799  if (grants != NULL)
7800  {
7801  gsize = set_size (grants);
7802  for (i = 0; i < gsize; i += GRANT_ENTRY_LENGTH)
7803  {
7804  au_print_grant_entry (grants, i, fp);
7805  }
7806  set_free (grants);
7807  }
7808 }
7809 
7810 /*
7811  * au_dump_auth() - Prints authorization info for all users.
7812  * return: none
7813  * fp(in): output file
7814  *
7815  * Note: The db_root class used to have a user attribute which was a set
7816  * containing the object-id for all users. The users attribute has been
7817  * eliminated for performance reasons. A query on the db_user class is
7818  * new used to find all users.
7819  */
7820 void
7821 au_dump_auth (FILE * fp)
7822 {
7823  MOP user, auth;
7824  char *query;
7825  DB_QUERY_RESULT *query_result;
7826  DB_QUERY_ERROR query_error;
7827  int error;
7828  DB_VALUE user_val;
7829  const char *qp1 = "select [%s] from [%s];";
7830 
7831  query = (char *) malloc (strlen (qp1) + strlen (AU_USER_CLASS_NAME) * 2);
7832 
7833  if (query)
7834  {
7835  sprintf (query, qp1, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME);
7836 
7837  error = db_compile_and_execute_local (query, &query_result, &query_error);
7838  /* error is row count if not negative. */
7839  if (error > 0)
7840  {
7841  while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS)
7842  {
7843  if (db_query_get_tuple_value (query_result, 0, &user_val) == NO_ERROR)
7844  {
7845  user = db_get_object (&user_val);
7846  if (au_get_object (user, "authorization", &auth) == NO_ERROR)
7847  {
7848  au_print_auth (auth, fp);
7849  }
7850  }
7851  }
7852  }
7853  if (error >= 0)
7854  {
7855  db_query_end (query_result);
7856  }
7857  free_and_init (query);
7858  }
7859 }
7860 
7861 /*
7862  * au_dump_user() - Dumps authorization information for a
7863  * particular user to a file.
7864  * return: none
7865  * user(in): user object
7866  * fp(in): file pointer
7867  */
7868 void
7869 au_dump_user (MOP user, FILE * fp)
7870 {
7871  DB_VALUE value;
7872  DB_SET *groups = NULL;
7873  MOP auth;
7874  int i, card;
7875 
7876  if (obj_get (user, "name", &value) == NO_ERROR)
7877  {
7879  db_get_string (&value));
7880  pr_clear_value (&value);
7881  }
7882 
7883  groups = NULL;
7884  if (au_get_set (user, "direct_groups", &groups) == NO_ERROR)
7885  {
7887  card = set_cardinality (groups);
7888  for (i = 0; i < card; i++)
7889  {
7890  if (set_get_element (groups, i, &value) == NO_ERROR)
7891  {
7892  if (obj_get (db_get_object (&value), "name", &value) == NO_ERROR)
7893  {
7894  fprintf (fp, "%s ", db_get_string (&value));
7895  pr_clear_value (&value);
7896  }
7897  }
7898  }
7899  fprintf (fp, "\n");
7900  set_free (groups);
7901  }
7902 
7903  groups = NULL;
7904  if (au_get_set (user, "groups", &groups) == NO_ERROR)
7905  {
7907  card = set_cardinality (groups);
7908  for (i = 0; i < card; i++)
7909  {
7910  if (set_get_element (groups, i, &value) == NO_ERROR)
7911  {
7912  if (obj_get (db_get_object (&value), "name", &value) == NO_ERROR)
7913  {
7914  fprintf (fp, "%s ", db_get_string (&value));
7915  pr_clear_value (&value);
7916  }
7917  }
7918  }
7919  fprintf (fp, "\n");
7920  set_free (groups);
7921  }
7922 
7923  /* dump local grants */
7924  if (au_get_object (user, "authorization", &auth) == NO_ERROR)
7925  {
7926  au_print_auth (auth, fp);
7927  }
7928 
7929  /*
7930  * need to do a walk back through the group hierarchy and collect all
7931  * inherited grants and their origins
7932  */
7933 }
7934 
7935 #if defined(ENABLE_UNUSED_FUNCTION)
7936 /*
7937  * au_print_class_auth() - Dumps authorization information for
7938  * a particular class.
7939  * return: none
7940  * class(in): class object
7941  *
7942  * Note: Used by the test program, should pass in a file pointer here !
7943  * The db_root class used to have a user attribute which was a set
7944  * containing the object-id for all users. The users attribute has been
7945  * eliminated for performance reasons. A query on the db_user class is
7946  * new used to find all users.
7947  */
7948 void
7949 au_print_class_auth (MOP class_mop)
7950 {
7951  MOP user;
7952  DB_SET *grants;
7953  int j, title, gsize;
7954  DB_VALUE element, value;
7955  char *query;
7956  DB_QUERY_RESULT *query_result;
7957  DB_QUERY_ERROR query_error;
7958  int error;
7959  DB_VALUE user_val;
7960  const char *qp1 = "select [%s] from [%s];";
7961 
7962  query = (char *) malloc (strlen (qp1) + strlen (AU_USER_CLASS_NAME) * 2);
7963 
7964  if (query)
7965  {
7966  sprintf (query, qp1, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME);
7967 
7968  error = db_compile_and_execute_local (query, &query_result, &query_error);
7969  /* error is row count if not negative. */
7970  if (error > 0)
7971  {
7972  while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS)
7973  {
7974  if (db_query_get_tuple_value (query_result, 0, &user_val) == NO_ERROR)
7975  {
7976  user = db_get_object (&user_val);
7977  title = 0;
7978  obj_get (user, "authorization", &value);
7979  get_grants (db_get_object (&value), &grants, 1);
7980  gsize = set_size (grants);
7981  for (j = 0; j < gsize; j += GRANT_ENTRY_LENGTH)
7982  {
7983  set_get_element (grants, GRANT_ENTRY_CLASS (j), &element);
7984  if (db_get_object (&element) == class_mop)
7985  {
7986  if (!title)
7987  {
7988  obj_get (user, "name", &value);
7989  if (db_get_string (&value) != NULL)
7990  {
7991  fprintf (stdout,
7994  }
7995  pr_clear_value (&value);
7996  title = 1;
7997  }
7998  au_print_grant_entry (grants, j, stdout);
7999  }
8000  }
8001  set_free (grants);
8002  }
8003  }
8004  }
8005  if (error >= 0)
8006  {
8007  db_query_end (query_result);
8008  }
8009  free_and_init (query);
8010  }
8011 }
8012 #endif /* ENABLE_UNUSED_FUNCTION */
8013 
8014 /*
8015  * au_dump_to_file() - Dump all authorization information including
8016  * user/group hierarchy.
8017  * return: none
8018  * fp(in): file pointer
8019  *
8020  * Note: The db_root class used to have a user attribute which was a set
8021  * containing the object-id for all users. The users attribute has been
8022  * eliminated for performance reasons. A query on the db_user class is
8023  * new used to find all users.
8024  */
8025 void
8026 au_dump_to_file (FILE * fp)
8027 {
8028  MOP user;
8029  DB_VALUE value;
8030  char *query = NULL;
8031  DB_QUERY_RESULT *query_result = NULL;
8032  DB_QUERY_ERROR query_error;
8033  int error = NO_ERROR;
8034  DB_VALUE user_val;
8035  const char *qp1 = "select [%s] from [%s];";
8036 
8037  /* NOTE: We should be getting the real user name here ! */
8038 
8040  Au_user_name);
8041 
8042  query = (char *) malloc (strlen (qp1) + strlen (AU_USER_CLASS_NAME) * 2);
8043 
8044  if (query)
8045  {
8046  sprintf (query, qp1, AU_USER_CLASS_NAME, AU_USER_CLASS_NAME);
8047 
8048  error = db_compile_and_execute_local (query, &query_result, &query_error);
8049  /* error is row count if not negative. */
8050  if (error > 0)
8051  {
8053  while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS)
8054  {
8055  if (db_query_get_tuple_value (query_result, 0, &user_val) == NO_ERROR)
8056  {
8057  user = db_get_object (&user_val);
8058  if (obj_get (user, "name", &value) == NO_ERROR)
8059  {
8060  fprintf (fp, "%s ", db_get_string (&value));
8061  pr_clear_value (&value);
8062  }
8063  }
8064  }
8065  fprintf (fp, "\n");
8066 
8067  if (db_query_first_tuple (query_result) == DB_CURSOR_SUCCESS)
8068  {
8069  do
8070  {
8071  if (db_query_get_tuple_value (query_result, 0, &user_val) == NO_ERROR)
8072  {
8073  user = db_get_object (&user_val);
8074  au_dump_user (user, fp);
8075  }
8076  }
8077  while (db_query_next_tuple (query_result) == DB_CURSOR_SUCCESS);
8078  }
8079  fprintf (fp, "\n");
8080  }
8081  }
8082  if (error >= 0 && query)
8083  {
8084  db_query_end (query_result);
8085  }
8086  if (query)
8087  {
8088  free_and_init (query);
8089  }
8090 
8092  au_dump_auth (fp);
8093 }
8094 
8095 /*
8096  * au_dump() -
8097  * return: none
8098  */
8099 void
8100 au_dump (void)
8101 {
8102  au_dump_to_file (stdout);
8103 }
8104 
8105 /*
8106  * au_describe_user_method() - Method interface to au_dump_user.
8107  * Can only be called when using the csql
8108  * interpreter since it dumps to stdout
8109  * return: none
8110  * user(in): user object
8111  * returnval(out): return value of this method
8112  */
8113 void
8115 {
8116  db_make_null (returnval);
8117  if (user != NULL)
8118  {
8119  au_dump_user (user, stdout);
8120  }
8121 }
8122 
8123 /*
8124  * au_info_method() - Method interface for authorization dump utilities.
8125  * return: none
8126  * class_mop(in): class object
8127  * returnval(out): return value of this method
8128  * info(in):
8129  *
8130  * Note: This should be conditionalized so it knows what kind of environment
8131  * this is (csql, esql).
8132  * For now this is documented to only work within csql because it dumps
8133  * to stdout.
8134  * There are some hidden parameters that trigger other dump routines.
8135  * This is a convenient hook for these things until we
8136  * have a more formal way to call them (if we ever do). These
8137  * are not documented in the user manual.
8138  */
8139 void
8140 au_info_method (MOP class_mop, DB_VALUE * returnval, DB_VALUE * info)
8141 {
8142  db_make_null (returnval);
8143 
8144  if (info != NULL && IS_STRING (info) && !DB_IS_NULL (info) && db_get_string (info) != NULL)
8145  {
8146  /* this dumps stuff to stdout */
8147  help_print_info (db_get_string (info), stdout);
8148  }
8149 }
8150 
8151 /*
8152  * au_describe_root_method() - Method interface for authorization dump
8153  * utilities
8154  * return: none
8155  * class_mop(in): class object
8156  * returnval(out): return value of this method
8157  * info(in):
8158  *
8159  * Note: This should be conditionalized so it knows what kind of environment
8160  * this is (csql, esql). For now this is documented to
8161  * only work within csql because it dumps to stdout.
8162  * There are some hidden parameters that trigger other dump routines.
8163  * This is a convenient hook for these things until we
8164  * have a more formal way to call them (if we ever do). These
8165  * are not documented in the user manual.
8166  */
8167 void
8168 au_describe_root_method (MOP class_mop, DB_VALUE * returnval, DB_VALUE * info)
8169 {
8170  db_make_null (returnval);
8171 
8172  if (info == NULL)
8173  {
8174  au_dump ();
8175  }
8176  else
8177  {
8178  /*
8179  * temporary, pass this through for older databases that still
8180  * have the "info" method pointing to this function
8181  */
8182  au_info_method (class_mop, returnval, info);
8183  }
8184 }
8185 
8186 
8187 /*
8188  * AUTHORIZATION CLASSES
8189  */
8190 
8191 /*
8192  * au_link_static_methods() - Called during the restart sequence to statically
8193  * link the authorization methods.
8194  * return: none
8195  */
8196 void
8198 {
8199  db_link_static_methods (&au_static_links[0]);
8200 }
8201 
8202 /*
8203  * au_install() - This is used to initialize the authorization system in a
8204  * freshly created database.
8205  * It should only be called within the createdb tool.
8206  * return: error code
8207  */
8208 int
8210 {
8211  MOP root = NULL, user = NULL, pass = NULL, auth = NULL, old = NULL;
8212  SM_TEMPLATE *def;
8213  int exists, save, index;
8214 
8215  AU_DISABLE (save);
8216 
8217  /*
8218  * create the system authorization objects, add attributes later since they
8219  * have domain dependencies
8220  */
8226 
8227  if (root == NULL || user == NULL || pass == NULL || auth == NULL || old == NULL)
8228  {
8229  goto exit_on_error;
8230  }
8231 
8232  sm_mark_system_class (root, 1);
8233  sm_mark_system_class (user, 1);
8234  sm_mark_system_class (pass, 1);
8235  sm_mark_system_class (auth, 1);
8236  sm_mark_system_class (old, 1);
8237 
8238  /*
8239  * db_root
8240  */
8241 
8242  /*
8243  * Authorization root, might not need this if we restrict the generation of
8244  * user and group objects but could be useful in other ways.
8245  */
8246  def = smt_edit_class_mop (root, AU_ALTER);
8247  if (def == NULL)
8248  {
8249  goto exit_on_error;
8250  }
8251  smt_add_attribute (def, "triggers", "sequence of (string, object)", (DB_DOMAIN *) 0);
8252  smt_add_attribute (def, "charset", "integer", NULL);
8253  smt_add_attribute (def, "lang", "string", NULL);
8254  smt_add_attribute (def, "timezone_checksum", "string", NULL);
8255 
8256 
8257  /* need signatures for these ! */
8258  smt_add_class_method (def, "add_user", "au_add_user_method");
8259  smt_add_class_method (def, "drop_user", "au_drop_user_method");
8260 
8261  smt_add_class_method (def, "find_user", "au_find_user_method");
8262  smt_assign_argument_domain (def, "find_user", true, NULL, 0, "string", (DB_DOMAIN *) 0);
8263 
8264  smt_add_class_method (def, "print_authorizations", "au_describe_root_method");
8265  smt_add_class_method (def, "info", "au_info_method");
8266  smt_add_class_method (def, "change_owner", "au_change_owner_method");
8267  smt_add_class_method (def, "change_trigger_owner", "au_change_trigger_owner_method");
8268  smt_add_class_method (def, "get_owner", "au_get_owner_method");
8269  smt_add_class_method (def, "change_sp_owner", "au_change_sp_owner_method");
8270 
8271  if (sm_update_class (def, NULL) != NO_ERROR || locator_create_heap_if_needed (root, false) == NULL)
8272  {
8273  goto exit_on_error;
8274  }
8275 
8276  /*
8277  * db_authorizations
8278  */
8279 
8280  /*
8281  * temporary support for the old name, need to migrate
8282  * users over to db_root
8283  */
8284  def = smt_edit_class_mop (old, AU_ALTER);
8285  if (def == NULL)
8286  {
8287  goto exit_on_error;
8288  }
8289  smt_add_class_method (def, "add_user", "au_add_user_method");
8290  smt_add_class_method (def, "drop_user", "au_drop_user_method");
8291 
8292  smt_add_class_method (def, "find_user", "au_find_user_method");
8293  smt_assign_argument_domain (def, "find_user", true, NULL, 0, "string", (DB_DOMAIN *) 0);
8294 
8295  smt_add_class_method (def, "print_authorizations", "au_describe_root_method");
8296  smt_add_class_method (def, "info", "au_info_method");
8297  smt_add_class_method (def, "change_owner", "au_change_owner_method");
8298  smt_add_class_method (def, "change_trigger_owner", "au_change_trigger_owner_method");
8299  smt_add_class_method (def, "get_owner", "au_get_owner_method");
8300 
8301  if (sm_update_class (def, NULL) != NO_ERROR || locator_create_heap_if_needed (old, false) == NULL)
8302  {
8303  goto exit_on_error;
8304  }
8305 
8306  /*
8307  * db_user
8308  */
8309 
8310  def = smt_edit_class_mop (user, AU_ALTER);
8311  if (def == NULL)
8312  {
8313  goto exit_on_error;
8314  }
8315  smt_add_attribute (def, "name", "string", (DB_DOMAIN *) 0);
8316  smt_add_attribute (def, "id", "integer", (DB_DOMAIN *) 0);
8317  smt_add_attribute (def, "password", AU_PASSWORD_CLASS_NAME, (DB_DOMAIN *) 0);
8318  smt_add_attribute (def, "direct_groups", "set of (db_user)", (DB_DOMAIN *) 0);
8319  smt_add_attribute (def, "groups", "set of (db_user)", (DB_DOMAIN *) 0);
8320  smt_add_attribute (def, "authorization", AU_AUTH_CLASS_NAME, (DB_DOMAIN *) 0);
8321  smt_add_attribute (def, "triggers", "sequence of object", (DB_DOMAIN *) 0);
8322  smt_add_attribute (def, "comment", "varchar(1024)", NULL);
8323  /* need signatures for these */
8324  smt_add_method (def, "set_password", "au_set_password_method");
8325  smt_add_method (def, "set_password_encoded", "au_set_password_encoded_method");
8326  smt_add_method (def, "set_password_encoded_sha1", "au_set_password_encoded_sha1_method");
8327  smt_add_method (def, "add_member", "au_add_member_method");
8328  smt_add_method (def, "drop_member", "au_drop_member_method");
8329  smt_add_method (def, "print_authorizations", "au_describe_user_method");
8330  smt_add_class_method (def, "add_user", "au_add_user_method");
8331  smt_add_class_method (def, "drop_user", "au_drop_user_method");
8332 
8333  smt_add_class_method (def, "find_user", "au_find_user_method");
8334  smt_assign_argument_domain (def, "find_user", true, NULL, 0, "string", (DB_DOMAIN *) 0);
8335  smt_add_class_method (def, "login", "au_login_method");
8336 
8337  if (sm_update_class (def, NULL) != NO_ERROR || locator_create_heap_if_needed (user, false) == NULL)
8338  {
8339  goto exit_on_error;
8340  }
8341 
8342  /* Add Unique Index */
8343  {
8344  const char *names[] = { "name", NULL };
8345 
8346  if (db_add_constraint (user, DB_CONSTRAINT_UNIQUE, NULL, names, 0) != NO_ERROR)
8347  {
8348  goto exit_on_error;
8349  }
8350  }
8351 
8352  /*
8353  * db_password
8354  */
8355 
8356  def = smt_edit_class_mop (pass, AU_ALTER);
8357  if (def == NULL)
8358  {
8359  goto exit_on_error;
8360  }
8361  smt_add_attribute (def, "password", "string", (DB_DOMAIN *) 0);
8362 
8363  if (sm_update_class (def, NULL) != NO_ERROR || locator_create_heap_if_needed (pass, false) == NULL)
8364  {
8365  goto exit_on_error;
8366  }
8367 
8368  /*
8369  * db_authorization
8370  */
8371 
8372  /*
8373  * Authorization object, the grant set could go directly in the user object
8374  * but it might be better to keep it separate in order to use the special
8375  * read-once lock for the authorization object only.
8376  */
8377 
8378  def = smt_edit_class_mop (auth, AU_ALTER);
8379  if (def == NULL)
8380  {
8381  goto exit_on_error;
8382  }
8383  smt_add_attribute (def, "owner", AU_USER_CLASS_NAME, (DB_DOMAIN *) 0);
8384  smt_add_attribute (def, "grants", "sequence", (DB_DOMAIN *) 0);
8385 
8386  if (sm_update_class (def, NULL) != NO_ERROR || locator_create_heap_if_needed (auth, false) == NULL)
8387  {
8388  goto exit_on_error;
8389  }
8390 
8391 
8392  /* Create the single authorization root object */
8393  Au_root = obj_create (root);
8394  if (Au_root == NULL)
8395  {
8396  goto exit_on_error;
8397  }
8398 
8399  /* create the DBA user and assign ownership of the system classes */
8400  Au_dba_user = au_add_user ("DBA", &exists);
8401  if (Au_dba_user == NULL)
8402  {
8403  goto exit_on_error;
8404  }
8405 
8406  /* establish the DBA as the current user */
8407  if (au_find_user_cache_index (Au_dba_user, &index, 0) != NO_ERROR)
8408  {
8409  goto exit_on_error;
8410  }
8411  Au_user = Au_dba_user;
8413 
8414  AU_SET_USER (Au_dba_user);
8415 
8416  au_change_owner (root, Au_user);
8417  au_change_owner (old, Au_user);
8418  au_change_owner (user, Au_user);
8419  au_change_owner (pass, Au_user);
8420  au_change_owner (auth, Au_user);
8421 
8422  /* create the PUBLIC user */
8423  Au_public_user = au_add_user ("PUBLIC", &exists);
8424  if (Au_public_user == NULL)
8425  {
8426  goto exit_on_error;
8427  }
8428 
8429  /*
8430  * grant browser access to the authorization objects
8431  * note that the password class cannot be read by anyone except the DBA
8432  */
8433  au_grant (Au_public_user, root, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false);
8434  au_grant (Au_public_user, old, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false);
8435  au_grant (Au_public_user, user, AU_SELECT, false);
8436  au_grant (Au_public_user, user, (DB_AUTH) (AU_SELECT | AU_EXECUTE), false);
8437  au_grant (Au_public_user, auth, AU_SELECT, false);
8438 
8440 
8441  AU_ENABLE (save);
8442  return NO_ERROR;
8443 
8444 exit_on_error:
8445  if (Au_public_user != NULL)
8446  {
8447  au_drop_user (Au_public_user);
8448  Au_public_user = NULL;
8449  }
8450  if (Au_dba_user != NULL)
8451  {
8452  au_drop_user (Au_dba_user);
8453  Au_dba_user = NULL;
8454  }
8455  if (Au_root != NULL)
8456  {
8457  obj_delete (Au_root);
8458  Au_root = NULL;
8459  }
8460  if (old != NULL)
8461  {
8462  db_drop_class (old);
8463  }
8464  if (auth != NULL)
8465  {
8466  db_drop_class (auth);
8467  }
8468  if (pass != NULL)
8469  {
8470  db_drop_class (pass);
8471  }
8472  if (user != NULL)
8473  {
8474  db_drop_class (user);
8475  }
8476  if (root != NULL)
8477  {
8478  db_drop_class (root);
8479  }
8480 
8481  AU_ENABLE (save);
8482  return (er_errid () == NO_ERROR ? ER_FAILED : er_errid ());
8483 }
8484 
8485 
8486 /*
8487  * RESTART/SHUTDOWN
8488  */
8489 
8490 /*
8491  * au_init() - This is called by bo_restart when the database
8492  * is being restarted.
8493  * It must only be called once.
8494  * return: none
8495  */
8496 void
8497 au_init (void)
8498 {
8499  Au_root = NULL;
8500  Au_authorizations_class = NULL;
8501  Au_authorization_class = NULL;
8502  Au_user_class = NULL;
8503  Au_password_class = NULL;
8504 
8505  Au_user = NULL;
8506  Au_public_user = NULL;
8507  Au_dba_user = NULL;
8508  Au_disable = 1;
8509 
8510  init_caches ();
8511 }
8512 
8513 /*
8514  * au_final() - Called during the bo_shutdown sequence.
8515  * return: none
8516  */
8517 void
8518 au_final (void)
8519 {
8520  Au_root = NULL;
8521  Au_authorizations_class = NULL;
8522  Au_authorization_class = NULL;
8523  Au_user_class = NULL;
8524  Au_password_class = NULL;
8525 
8526  Au_user = NULL;
8527  Au_public_user = NULL;
8528  Au_dba_user = NULL;
8529  Au_disable = 1;
8530 
8531  /*
8532  * could remove the static links here but it isn't necessary and
8533  * we may need them again the next time we restart
8534  */
8535 
8536  flush_caches ();
8537 }
8538 
8539 /*
8540  * au_get_class_privilege() -
8541  * return: error code
8542  * mop(in):
8543  * auth(in):
8544  */
8545 int
8546 au_get_class_privilege (DB_OBJECT * mop, unsigned int *auth)
8547 {
8548  SM_CLASS *class_;
8549  AU_CLASS_CACHE *cache;
8550  unsigned int bits = 0;
8551  int error = NO_ERROR;
8552 
8553  if (!Au_disable)
8554  {
8555  if (mop == NULL)
8556  {
8557  return ER_FAILED;
8558  }
8559 
8560  class_ = (SM_CLASS *) mop->object;
8561 
8562  cache = (AU_CLASS_CACHE *) class_->auth_cache;
8563  if (cache == NULL)
8564  {
8565  cache = au_install_class_cache (class_);
8566  if (cache == NULL)
8567  {
8568  assert (er_errid () != NO_ERROR);
8569  return er_errid ();
8570  }
8571  }
8572 
8573  bits = cache->data[Au_cache_index];
8574  if (bits == AU_CACHE_INVALID)
8575  {
8576  error = update_cache (mop, class_, cache);
8577  if (error == NO_ERROR)
8578  {
8579  bits = cache->data[Au_cache_index];
8580  }
8581  }
8582  *auth = bits;
8583  }
8584 
8585  return error;
8586 }
8587 
8588 /*
8589  * get_attribute_number - attribute number of the given attribute/class
8590  * return:
8591  * arg1(in):
8592  * arg2(in):
8593  */
8594 void
8595 get_attribute_number (DB_OBJECT * target, DB_VALUE * result, DB_VALUE * attr_name)
8596 {
8597  int attrid, shared;
8598  DB_DOMAIN *dom;
8599 
8600  db_make_null (result);
8601 
8602  if (DB_VALUE_TYPE (attr_name) != DB_TYPE_STRING)
8603  return;
8604 
8605  /* we will only look for regular attributes and not class attributes. this is a limitation of this method. */
8606  if (sm_att_info (target, db_get_string (attr_name), &attrid, &dom, &shared, 0 /* non-class attrs */ )
8607  < 0)
8608  return;
8609 
8610  db_make_int (result, attrid);
8611 }
8612 
8613 
8614 /*
8615  * au_disable - set Au_disable true
8616  * return: original Au_disable value
8617  */
8618 int
8620 {
8621  int save = Au_disable;
8622  Au_disable = 1;
8623  return save;
8624 }
8625 
8626 /*
8627  * au_enable - restore Au_disable
8628  * return:
8629  * save(in): original Au_disable value
8630  */
8631 void
8632 au_enable (int save)
8633 {
8634  Au_disable = save;
8635 }
8636 
8637 /*
8638  * au_public_user
8639  * return: Au_public_user
8640  */
8641 MOP
8643 {
8644  return Au_public_user;
8645 }
8646 
8647 /*
8648  * au_public_user
8649  * return: Au_public_user
8650  */
8651 MOP
8653 {
8654  return Au_dba_user;
8655 }
8656 
8657 /*
8658  * au_check_serial_authorization - check whether the current user is able to
8659  * modify serial object or not
8660  * return: NO_ERROR if available, otherwise error code
8661  * serial_object(in): serial object pointer
8662  */
8663 int
8665 {
8666  DB_VALUE creator_val;
8667  MOP creator;
8668  DB_SET *groups;
8669  int ret_val;
8670 
8671  ret_val = db_get (serial_object, "owner", &creator_val);
8672 
8673  if (ret_val != NO_ERROR || DB_IS_NULL (&creator_val))
8674  {
8675  return ret_val;
8676  }
8677 
8678  creator = db_get_object (&creator_val);
8679 
8681 
8682  if (ws_is_same_object (creator, Au_user) || au_is_dba_group_member (Au_user))
8683  {
8684  ret_val = NO_ERROR;
8685  }
8686  else if (au_get_set (Au_user, "groups", &groups) == NO_ERROR)
8687  {
8688  if (set_ismember (groups, &creator_val))
8689  {
8690  ret_val = NO_ERROR;
8691  }
8692  set_free (groups);
8693  }
8694 
8695  if (ret_val != NO_ERROR)
8696  {
8697  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ret_val, 0);
8698  }
8699 
8700  pr_clear_value (&creator_val);
8701 
8702  return ret_val;
8703 }
8704 
8705 const char *
8707 {
8708  return AU_PUBLIC_USER_NAME;
8709 }
8710 
8711 const char *
8713 {
8714  return AU_USER_CLASS_NAME;
8715 }
#define UNIQUE_PARTITION_SAVEPOINT_REVOKE
DB_OBJECT * db_find_class(const char *name)
Definition: db_info.c:133
int au_check_serial_authorization(MOP serial_object)
LC_FETCH_VERSION_TYPE
Definition: locator.h:178
static CLASS_USER * find_or_add_user(CLASS_AUTH *auth, MOP user_obj)
void au_final(void)
#define ER_LK_UNILATERALLY_ABORTED
Definition: error_code.h:130
int db_execute_statement_local(DB_SESSION *session, int stmt, DB_QUERY_RESULT **result)
Definition: db_vdb.c:2939
int au_find_user_to_drop(const char *user_name, MOP *user)
int tran_system_savepoint(const char *savept_name)
#define ER_AU_PASSWORD_OVERFLOW
Definition: error_code.h:236
struct class_user * user
Definition: authenticate.c:259
#define CT_CLASSAUTH_NAME
Definition: transform.h:130
struct au_user_cache * next
Definition: authenticate.c:243
#define WS_IS_DELETED(mop)
Definition: work_space.h:284
#define PASSWORD_ENCRYPTION_SEED
Definition: authenticate.c:135
#define NO_ERROR
Definition: error_code.h:46
static DB_OBJECT * Au_authorization_class
Definition: authenticate.c:375
#define ER_AU_CORRUPTED
Definition: error_code.h:201
#define AU_DISABLE(save)
Definition: authenticate.h:106
void au_reset_authorization_caches(void)
int set_drop_seq_element(DB_COLLECTION *set, int index)
Definition: set_object.c:2902
void au_add_user_method(MOP class_mop, DB_VALUE *returnval, DB_VALUE *name, DB_VALUE *password)
DB_COLLECTION * db_get_set(const DB_VALUE *value)
void er_stack_push(void)
MOBJ vid_fetch_instance(MOP mop, DB_FETCH_MODE purpose, LC_FETCH_VERSION_TYPE read_fetch_version_type)
static MOP au_get_new_auth(MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type)
#define LANG_SYS_COLLATION
#define AU_GRANT_MASK
Definition: authenticate.h:85
#define ER_AU_MEMBER_CAUSES_CYCLES
Definition: error_code.h:206
static char * dbuser
static int get_grants(MOP auth, DB_SET **grant_ptr, int filter)
#define ER_AU_COMMENT_OVERFLOW
Definition: error_code.h:1495
#define AU_MAX_PASSWORD_CHARS
Definition: authenticate.h:143
int grant_index
Definition: authenticate.c:203
#define GRANT_ENTRY_CLASS(index)
Definition: authenticate.c:131
#define ENCODE_PREFIX_SHA1
Definition: authenticate.c:138
char Au_user_password_des_oldstyle[AU_MAX_PASSWORD_BUF+4]
Definition: authenticate.c:358
#define AU_TYPE_MASK
Definition: authenticate.h:84
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
void au_dump_to_file(FILE *fp)
static int Au_ignore_passwords
Definition: authenticate.c:323
enum au_fetchmode AU_FETCHMODE
#define ER_AU_CLASS_WITH_NO_OWNER
Definition: error_code.h:207
static AU_CLASS_CACHE * au_install_class_cache(SM_CLASS *sm_class)
Definition: authenticate.c:760
#define IS_ENCODED_DES(string)
Definition: authenticate.c:140
int obj_delete(MOP op)
char * MOBJ
Definition: work_space.h:174
static void encrypt_password(const char *pass, int add_prefix, char *dest)
MOP Au_root
Definition: authenticate.c:300
int sm_mark_system_class(MOP classop, int on_or_off)
#define AU_DELETE
Definition: authenticate.h:72
#define TP_IS_SET_TYPE(typenum)
void dbmeth_print(DB_OBJECT *self, DB_VALUE *result, DB_VALUE *msg)
int db_Connect_status
Definition: db_macro.c:88
#define ER_AU_CANT_GRANT_OWNER
Definition: error_code.h:210
void set_free(DB_COLLECTION *set)
Definition: set_object.c:2560
DB_SESSION * db_open_buffer_local(const char *buffer)
Definition: db_vdb.c:205
int db_get_int(const DB_VALUE *value)
MOBJ locator_create_heap_if_needed(MOP class_mop, bool reuse_oid)
Definition: locator_cl.c:5690
void au_dump_auth(FILE *fp)
static int Au_cache_max
Definition: authenticate.c:408
#define ER_FAILED
Definition: error_code.h:47
int db_make_varchar(DB_VALUE *value, const int max_char_length, DB_CONST_C_CHAR str, const int char_str_byte_size, const int codeset, const int collation_id)
int log_does_active_user_exist(const char *user_name, bool *existed)
int au_force_write_new_auth(void)
static int check_user_name(const char *name)
#define MSGCAT_AUTH_CLASS_NAME
Definition: authenticate.c:85
#define ER_AU_USER_EXISTS
Definition: error_code.h:228
static int fetch_instance(MOP op, MOBJ *obj_ptr, AU_FETCHMODE fetchmode, LC_FETCH_VERSION_TYPE read_fetch_version_type)
void qo_set_cost(DB_OBJECT *target, DB_VALUE *result, DB_VALUE *plan, DB_VALUE *cost)
static void remove_user_cache_references(MOP user)
#define ER_USER_NAME_TOO_LONG
Definition: error_code.h:1377
static void au_print_cache(int cache, FILE *fp)
int crypt_sha_two(THREAD_ENTRY *thread_p, const char *src, int src_len, int need_hash_len, char **dest_p, int *dest_len_p)
Definition: crypt_opfunc.c:490
#define ER_AU_CANT_ADD_MEMBER
Definition: error_code.h:205
#define IS_CATALOG_CLASS(name)
Definition: authenticate.c:150
void * auth_cache
Definition: class_object.h:751
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
#define DB_AUTH_ALL
Definition: dbtype_def.h:157
int au_revoke(MOP user, MOP class_mop, DB_AUTH type)
static int au_add_member_internal(MOP group, MOP member, int new_user)
#define ASSERT_ERROR_AND_SET(error_code)
int db_query_end(DB_QUERY_RESULT *result)
Definition: db_query.c:3362
static int class_grant_loop(print_output &output_ctx, CLASS_AUTH *auth)
static void free_class_users(CLASS_USER *users)
int crypt_encrypt_printable(const char *line, char *crypt, int maxlen)
Definition: encryption.c:91
static AU_CLASS_CACHE * au_make_class_cache(int depth)
Definition: authenticate.c:705
int db_make_object(DB_VALUE *value, DB_C_OBJECT *obj)
static int au_perform_login(const char *name, const char *password, bool ignore_dba_privilege)
int au_check_user(void)
DB_COLLECTION * set_create_sequence(int size)
Definition: set_object.c:2432
MOP obj_find_unique(MOP op, const char *attname, DB_VALUE *value, AU_FETCHMODE fetchmode)
#define BOOT_IS_CLIENT_RESTARTED()
Definition: boot_cl.h:42
int au_fetch_class_by_instancemop(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
int intl_identifier_upper_string_size(const char *src)
bool au_is_dba_group_member(MOP user)
const char * AU_PASSWORD_CLASS_NAME
Definition: authenticate.c:108
static int collect_class_grants(MOP class_mop, DB_AUTH type, MOP revoked_auth, int revoked_grant_index, AU_GRANT **return_grants)
static int add_grant_entry(DB_SET *grants, MOP class_mop, MOP grantor)
void au_set_password_encoded_sha1_method(MOP user, DB_VALUE *returnval, DB_VALUE *password)
void au_drop_user_method(MOP root, DB_VALUE *returnval, DB_VALUE *name)
static int is_protected_class(MOP classmop, SM_CLASS *sm_class, DB_AUTH auth)
#define ER_AU_INSERT_FAILURE
Definition: error_code.h:224
struct sm_component * next
Definition: class_object.h:384
MOP au_get_dba_user(void)
const char * AU_USER_CLASS_NAME
Definition: authenticate.c:107
void au_disable_passwords(void)
int db_make_sequence(DB_VALUE *value, DB_C_SET *set)
#define ER_TR_TRIGGER_NOT_FOUND
Definition: error_code.h:592
static void free_grant_list(AU_GRANT *grants)
DB_OBJECT * dbt_finish_object(DB_OTMPL *def)
Definition: db_obj.c:560
MOBJ locator_fetch_class_of_instance(MOP inst_mop, MOP *class_mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:2354
#define AU_RESTORE(save)
Definition: authenticate.h:133
static int au_get_set(MOP obj, const char *attname, DB_SET **set)
Definition: authenticate.c:573
#define AU_GRANT_SHIFT
Definition: authenticate.h:94
#define GRANT_ENTRY_SOURCE(index)
Definition: authenticate.c:132
#define MSGCAT_AUTH_CURRENT_USER
Definition: authenticate.c:94
#define IS_ENCODED_SHA1(string)
Definition: authenticate.c:141
int au_disable(void)
int er_errid(void)
CLASS_GRANT * grants
Definition: authenticate.c:275
static int find_grant_entry(DB_SET *grants, MOP class_mop, MOP grantor)
void db_string_free(char *string)
Definition: db_admin.c:2596
int au_export_users(print_output &output_ctx)
void dbt_abort_object(DB_OTMPL *def)
Definition: db_obj.c:616
int set_size(DB_COLLECTION *set)
Definition: set_object.c:3036
#define AU_MAX_PASSWORD_BUF
Definition: authenticate.h:144
#define AU_SET_USER
Definition: authenticate.h:141
MOP Au_public_user
Definition: authenticate.c:333
#define ER_AU_INVALID_CLASS
Definition: error_code.h:833
int au_change_sp_owner(MOP sp, MOP owner)
SM_CLASS * class_
Definition: authenticate.c:228
void db_ws_free(void *ptr)
Definition: quick_fit.c:194
#define CT_CLASS_NAME
Definition: transform.h:119
bool ws_is_same_object(MOP mop1, MOP mop2)
Definition: work_space.c:5065
DB_OBJECT * db_create_class(const char *name)
Definition: db_class.c:70
const char * AU_PUBLIC_USER_NAME
Definition: authenticate.c:112
#define AU_ALTER
Definition: authenticate.h:73
#define MSGCAT_AUTH_USER_GROUPS
Definition: authenticate.c:92
static DB_METHOD_LINK au_static_links[]
Definition: authenticate.c:439
#define ER_AU_ALTER_FAILURE
Definition: error_code.h:222
void ws_free_string(const char *str)
Definition: work_space.c:3480
#define MSGCAT_AUTH_USER_TITLE
Definition: authenticate.c:87
int au_install(void)
#define ER_AU_MULTIPLE_ROOTS
Definition: error_code.h:219
#define ENCODE_PREFIX_DES
Definition: authenticate.c:137
static int au_extend_class_caches(int *index)
Definition: authenticate.c:820
static void init_caches(void)
int dbt_put_internal(DB_OTMPL *def, const char *name, DB_VALUE *value)
Definition: db_obj.c:670
struct class_user * next
Definition: authenticate.c:271
#define CT_SERIAL_NAME
Definition: transform.h:135
void er_stack_pop_and_keep_error(void)
static DB_OBJECT * is_class(OID *obj_oid, OID *class_oid)
Definition: compactdb.c:637
bool set_ismember(DB_COLLECTION *set, DB_VALUE *value)
Definition: set_object.c:3199
MOBJ locator_fetch_class(MOP class_mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:2293
struct au_grant * next
Definition: authenticate.c:196
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
void au_dump(void)
DB_OBJECT * tr_find_trigger(const char *name)
#define AU_EXECUTE
Definition: authenticate.h:75
#define DB_CONNECTION_STATUS_CONNECTED
Definition: db.h:47
#define ER_AU_NOT_OWNER
Definition: error_code.h:231
int STATEMENT_ID
Definition: dbtype_def.h:302
DB_OBJECT * db_create_internal(DB_OBJECT *obj)
Definition: db_obj.c:93
MOP Au_dba_user
Definition: authenticate.c:334
int sm_issystem(SM_CLASS *class_)
#define UNIQUE_PARTITION_SAVEPOINT_OWNER
const char * AU_DBA_USER_NAME
Definition: authenticate.c:113
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
Definition: db_set.h:35
const char * sm_ch_name(const MOBJ clobj)
static int propagate_revoke(AU_GRANT *grant_list, MOP owner, DB_AUTH mask)
#define ER_QPROC_SERIAL_NOT_FOUND
Definition: error_code.h:965
int au_change_trigger_owner(MOP trigger, MOP owner)
static int au_update_new_auth(MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, int grant_option)
int tran_abort_upto_system_savepoint(const char *savepoint_name)
int db_set_system_generated_statement(DB_SESSION *session)
Definition: db_vdb.c:3173
const char * AU_ROOT_CLASS_NAME
Definition: authenticate.c:104
#define assert(x)
static char Au_user_name[DB_MAX_USER_LENGTH+4]
Definition: authenticate.c:357
void au_add_member_method(MOP user, DB_VALUE *returnval, DB_VALUE *memval)
void dbmeth_class_name(DB_OBJECT *self, DB_VALUE *result)
int set_filter(DB_COLLECTION *set)
Definition: set_object.c:3744
#define ER_AU_CANT_REVOKE_OWNER
Definition: error_code.h:215
MOP jsp_find_stored_procedure(const char *name)
Definition: jsp_cl.c:227
#define ER_AU_CANT_DROP_USER
Definition: error_code.h:233
static int add_class_grant(CLASS_AUTH *auth, MOP source, MOP user, int cache)
static AU_USER_CACHE * Au_user_cache
Definition: authenticate.c:384
#define ER_AU_GRANT_NOT_FOUND
Definition: error_code.h:216
int db_make_set(DB_VALUE *value, DB_C_SET *set)
MOP au_add_user(const char *name, int *exists)
#define IS_STRING(n)
Definition: authenticate.c:147
#define ER_GENERIC_ERROR
Definition: error_code.h:49
#define IS_ENCODED_SHA2_512(string)
Definition: authenticate.c:142
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
int ws_pin(MOP mop, int pin)
Definition: work_space.c:2989
#define ER_AU_INCOMPLETE_AUTH
Definition: error_code.h:218
struct db_object * class_mop
Definition: work_space.h:121
static int appropriate_error(unsigned int bits, unsigned int requested)
int db_query_first_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2309
void help_print_info(const char *command, FILE *fpp)
Definition: object_print.c:595
static int au_compute_groups(MOP member, const char *name)
const char * au_get_user_class_name(void)
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
int smt_assign_argument_domain(SM_TEMPLATE *template_, const char *name, int class_method, const char *implementation, int index, const char *domain_string, DB_DOMAIN *domain)
int sm_check_catalog_rep_dir(MOP classmop, SM_CLASS *class_)
#define OID_ISTEMP(oidp)
Definition: oid.h:80
void lang_set_parser_use_client_charset(bool use)
void db_objlist_free(DB_OBJLIST *list)
Definition: db_admin.c:2612
void au_set_password_method(MOP user, DB_VALUE *returnval, DB_VALUE *password)
void au_check_authorization_method(MOP obj, DB_VALUE *returnval, DB_VALUE *class_, DB_VALUE *auth)
static int check_grant_option(MOP classop, SM_CLASS *sm_class, DB_AUTH type)
static void au_print_grant_entry(DB_SET *grants, int grant_index, FILE *fp)
int au_set_password(MOP user, const char *password)
static int au_set_new_auth(MOP au_obj, MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, bool grant_option)
#define MSGCAT_AUTH_USER_NAME
Definition: authenticate.c:89
struct class_grant * next
Definition: authenticate.c:257
int au_drop_member(MOP group, MOP member)
void(* METHOD_LINK_FUNCTION)()
Definition: dbtype_def.h:332
void crypt_seed(const char *key)
Definition: encryption.c:62
void au_set_password_encoded_method(MOP user, DB_VALUE *returnval, DB_VALUE *password)
#define DB_IS_STRING(value)
Definition: dbtype.h:65
int locator_flush_class(MOP class_mop)
Definition: locator_cl.c:5068
void au_change_owner_method(MOP obj, DB_VALUE *returnval, DB_VALUE *class_, DB_VALUE *owner)
static enum scanner_mode mode
bool au_has_user_name(void)
#define ER_AU_NO_USER_LOGGED_IN
Definition: error_code.h:234
int au_change_owner(MOP classmop, MOP owner)
int available_auth
Definition: authenticate.c:276
const char * sm_get_ch_name(MOP op)
DB_OBJECT * db_get_object(const DB_VALUE *value)
#define IS_ENCODED_ANY(string)
Definition: authenticate.c:143
int db_fetch_set(DB_SET *set, DB_FETCH_MODE purpose, int quit_on_error)
Definition: db_admin.c:2372
static int build_class_grant_list(CLASS_AUTH *cl_auth, MOP class_mop)
int au_check_authorization(MOP op, DB_AUTH auth)
#define ENCODE_PREFIX_SHA2_512
Definition: authenticate.c:139
MOP ws_class_mop(MOP mop)
Definition: work_space.c:2907
void db_link_static_methods(DB_METHOD_LINK *methods)
Definition: db_admin.c:2523
static CLASS_GRANT * make_class_grant(CLASS_USER *user, int cache)
void db_set_read_fetch_instance_version(LC_FETCH_VERSION_TYPE read_Fetch_Instance_Version)
Definition: db_vdb.c:3904
#define MSGCAT_AUTH_INVALID_CACHE
Definition: authenticate.c:84
#define SP_ATTR_OWNER
Definition: jsp_cl.h:47
static void free_class_grants(CLASS_GRANT *grants)
void au_info_method(MOP class_mop, DB_VALUE *returnval, DB_VALUE *info)
#define WS_SET_DELETED(mop)
Definition: work_space.h:286
int au_add_member(MOP group, MOP member)
int au_set_user(MOP newuser)
#define ER_AU_USER_HAS_DATABASE_OBJECTS
Definition: error_code.h:1044
#define AU_NO_AUTHORIZATION
Definition: authenticate.h:87
#define NULL
Definition: freelistheap.h:34
#define ER_AU_UPDATE_FAILURE
Definition: error_code.h:223
MOP au_find_user(const char *user_name)
#define ER_AU_CANT_REVOKE_SELF
Definition: error_code.h:214
static int au_fetch_class_internal(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type, FETCH_BY fetch_by)
#define ER_OBJ_OBJECT_NOT_FOUND
Definition: error_code.h:873
if(extra_options)
Definition: dynamic_load.c:958
DB_SESSION * db_open_buffer(const char *buffer)
Definition: db_vdb.c:232
static CLASS_USER * make_class_user(MOP user_obj)
#define AU_CACHE_INVALID
Definition: authenticate.h:98
int db_compile_statement(DB_SESSION *session)
Definition: db_vdb.c:766
void db_close_session(DB_SESSION *session)
Definition: db_vdb.c:3319
int au_export_grants(print_output &output_ctx, MOP class_mop)
static void au_print_auth(MOP auth, FILE *fp)
OID * sm_ch_rep_dir(MOBJ clobj)
static void free_user_cache(AU_USER_CACHE *u)
Definition: authenticate.c:956
int db_set_add(DB_SET *set, DB_VALUE *value)
Definition: db_set.c:465
int au_fetch_instance_force(MOP op, MOBJ *obj_ptr, AU_FETCHMODE fetchmode, LC_FETCH_VERSION_TYPE fetch_version_type)
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
void au_enable(int save)
#define TM_TRAN_READ_FETCH_VERSION()
void au_free_authorization_cache(void *cache)
Definition: authenticate.c:784
SM_TEMPLATE * smt_edit_class_mop(MOP op, DB_AUTH db_auth_type)
#define ER_SP_NOT_EXIST
Definition: error_code.h:1115
LOCK lock
Definition: work_space.h:134
int smt_add_method(SM_TEMPLATE *template_, const char *name, const char *function)
MOBJ locator_fetch_instance(MOP mop, DB_FETCH_MODE purpose, LC_FETCH_VERSION_TYPE fetch_version_type)
Definition: locator_cl.c:2393
#define MSGCAT_AUTH_UNDEFINED_USER
Definition: authenticate.c:88
int set_get_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2575
struct db_objlist * next
Definition: dbtype_def.h:442
const char * AU_OLD_ROOT_CLASS_NAME
Definition: authenticate.c:105
char * db_get_user_name(void)
Definition: db_admin.c:1911
static void issue_grant_statement(print_output &output_ctx, CLASS_AUTH *auth, CLASS_GRANT *grant, int authbits)
static int au_get_object(MOP obj, const char *attname, MOP *mop_ptr)
Definition: authenticate.c:628
int au_grant(MOP user, MOP class_mop, DB_AUTH type, bool grant_option)
#define AU_MAX_BIT
int pr_clear_value(DB_VALUE *value)
void sm_bump_local_schema_version(void)
#define MSGCAT_CATALOG_CUBRID
MOBJ locator_update_instance(MOP mop)
Definition: locator_cl.c:6035
#define AU_INSERT
Definition: authenticate.h:70
void er_stack_pop(void)
#define ER_AU_DELETE_FAILURE
Definition: error_code.h:225
struct au_class_cache AU_CLASS_CACHE
Definition: authenticate.c:223
int au_fetch_class_by_classmop(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
#define ER_AU_INVALID_USER_NAME
Definition: error_code.h:697
void au_change_serial_owner_method(MOP obj, DB_VALUE *returnval, DB_VALUE *serial, DB_VALUE *owner)
#define ER_OBJ_INVALID_ARGUMENT
Definition: error_code.h:946
static int Au_cache_depth
Definition: authenticate.c:407
struct db_object * op
Definition: dbtype_def.h:443
int set_cardinality(DB_COLLECTION *set)
Definition: set_object.c:2999
void au_describe_user_method(MOP user, DB_VALUE *returnval)
MOP Au_user
Definition: authenticate.c:343
#define ER_AU_MISSING_CLASS
Definition: error_code.h:202
static int au_set_get_obj(DB_SET *set, int index, MOP *obj)
Definition: authenticate.c:664
int set_put_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2719
#define AU_FULL_AUTHORIZATION
Definition: authenticate.h:86
static void error(const char *msg)
Definition: gencat.c:331
void get_attribute_number(DB_OBJECT *target, DB_VALUE *result, DB_VALUE *attr_name)
static int Au_cache_index
Definition: authenticate.c:419
const char * AU_GRANT_CLASS_NAME
Definition: authenticate.c:110
#define ER_AU_INVALID_PASSWORD
Definition: error_code.h:235
#define AU_UPDATE
Definition: authenticate.h:71
DB_OBJLIST * sm_fetch_all_objects(DB_OBJECT *op, DB_FETCH_MODE purpose)
int db_drop_class(MOP class_)
Definition: db_class.c:110
int sm_att_info(MOP classop, const char *name, int *idp, TP_DOMAIN **domainp, int *sharedp, int class_attr)
int db_query_next_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2088
static int apply_grants(MOP auth, MOP class_mop, unsigned int *bits)
MOP au_get_class_owner(MOP classmop)
static MOP au_make_user(const char *name)
#define MSGCAT_AUTH_GRANT_DUMP_ERROR
Definition: authenticate.c:97
#define MSGCAT_AUTH_FROM_USER
Definition: authenticate.c:86
#define AU_SELECT
Definition: authenticate.h:69
#define MSGCAT_AUTH_AUTH_TITLE
Definition: authenticate.c:98
#define ER_AU_INVALID_USER
Definition: error_code.h:229
static int au_propagate_del_new_auth(AU_GRANT *glist, DB_AUTH mask)
DB_AUTH
Definition: dbtype_def.h:239
#define ARG_FILE_LINE
Definition: error_manager.h:44
#define ER_AU_DBA_ONLY
Definition: error_code.h:204
static DB_OBJECT * Au_user_class
Definition: authenticate.c:376
int sm_partitioned_class_type(DB_OBJECT *classop, int *partition_type, char *keyattr, MOP **partitions)
int au_get_class_privilege(DB_OBJECT *mop, unsigned int *auth)
void au_dump_user(MOP user, FILE *fp)
#define WS_OID(mop)
Definition: work_space.h:293
int obj_set(MOP op, const char *name, DB_VALUE *value)
#define ER_AU_SELECT_FAILURE
Definition: error_code.h:221
#define AU_ENABLE(save)
Definition: authenticate.h:113
MOP obj_create(MOP classop)
void au_link_static_methods(void)
const char * au_get_public_user_name(void)
static void drop_grant_entry(DB_SET *grants, int index)
int db_make_error(DB_VALUE *value, const int errcode)
int clogin_user(const char *username)
void * object
Definition: work_space.h:123
#define free_and_init(ptr)
Definition: memory_alloc.h:147
MOP auth_object
Definition: authenticate.c:198
#define strlen(s1)
Definition: intl_support.c:43
enum fetch_by FETCH_BY
Definition: authenticate.c:185
SM_COMPONENT header
Definition: class_object.h:441
#define ER_AU_MEMBER_NOT_FOUND
Definition: error_code.h:232
#define ER_OBJ_INVALID_ARGUMENTS
Definition: error_code.h:275
int db_push_values(DB_SESSION *session, int count, DB_VALUE *in_values)
Definition: db_vdb.c:1527
void help_print_describe_comment(print_output &output_ctx, const char *comment)
Definition: object_print.c:716
int obj_inst_lock(MOP op, int for_write)
static void encrypt_password_sha2_512(const char *pass, char *dest)
#define ER_HEAP_UNKNOWN_OBJECT
Definition: error_code.h:102
#define MSGCAT_AUTH_USER_DIRECT_GROUPS
Definition: authenticate.c:99
void au_change_sp_owner_method(MOP obj, DB_VALUE *returnval, DB_VALUE *sp, DB_VALUE *owner)
#define DB_CURSOR_SUCCESS
Definition: dbtype_def.h:166
int db_get(DB_OBJECT *object, const char *attpath, DB_VALUE *value)
Definition: db_obj.c:233
#define GRANT_ENTRY_CACHE(index)
Definition: authenticate.c:133
void ml_ext_free(DB_OBJLIST *list)
Definition: work_space.c:4806
char * au_user_name_dup(void)
static const char * auth_type_name[]
Definition: authenticate.c:421
#define AU_MIN_BIT
#define AU_SAVE_AND_DISABLE(save)
Definition: authenticate.h:126
int au_start(void)
void * db_ws_alloc(size_t size)
Definition: quick_fit.c:73
char Au_user_password_sha2_512[AU_MAX_PASSWORD_BUF+4]
Definition: authenticate.c:360
static int check_authorization(MOP classobj, SM_CLASS *sm_class, DB_AUTH type)
MOP au_get_public_user(void)
void er_clear(void)
char Au_user_password_sha1[AU_MAX_PASSWORD_BUF+4]
Definition: authenticate.c:359
#define ER_AU_ACCESS_ERROR
Definition: error_code.h:203
static int fetch_class(MOP op, MOP *return_mop, SM_CLASS **return_class, AU_FETCHMODE fetchmode, FETCH_BY fetch_by)
#define MSGCAT_SET_AUTHORIZATION
fetch_by
Definition: authenticate.c:179
static DB_OBJECT * Au_password_class
Definition: authenticate.c:377
bool catcls_Enable
static void reset_cache_for_user_and_class(SM_CLASS *sm_class)
Definition: authenticate.c:984
unsigned int data[1]
Definition: authenticate.c:229
int au_login(const char *name, const char *password, bool ignore_dba_privilege)
int au_add_method_check_authorization(void)
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
char * msgcat_message(int cat_id, int set_id, int msg_id)
#define AU_INDEX
Definition: authenticate.h:74
void au_describe_root_method(MOP class_mop, DB_VALUE *returnval, DB_VALUE *info)
#define DB_IS_NULL(value)
Definition: dbtype.h:63
#define ER_OBJ_DOMAIN_CONFLICT
Definition: error_code.h:285
DB_OTMPL * dbt_edit_object(MOP object)
Definition: db_obj.c:533
#define UNIQUE_PARTITION_SAVEPOINT_GRANT
int smt_add_attribute(SM_TEMPLATE *template_, const char *name, const char *domain_string, DB_DOMAIN *domain)
MOP sm_get_class(MOP obj)
MOBJ locator_update_class(MOP mop)
Definition: locator_cl.c:5938
char * au_get_user_name(MOP obj)
#define ER_NOT_ALLOWED_ACCESS_TO_PARTITION
Definition: error_code.h:1137
unsigned is_temp
Definition: work_space.h:149
int obj_get(MOP op, const char *name, DB_VALUE *value)
char * strdup(const char *str)
Definition: porting.c:901
DB_OBJLIST * db_get_all_objects(DB_OBJECT *op)
Definition: db_info.c:246
int au_fetch_instance(MOP op, MOBJ *obj_ptr, AU_FETCHMODE mode, LC_FETCH_VERSION_TYPE fetch_version_type, DB_AUTH type)
DB_FETCH_MODE
Definition: dbtype_def.h:215
void au_get_owner_method(MOP obj, DB_VALUE *returnval, DB_VALUE *class_)
MOP sm_Root_class_mop
void au_find_user_method(MOP class_mop, DB_VALUE *returnval, DB_VALUE *name)
const char * TR_ATT_OWNER
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
int db_make_int(DB_VALUE *value, const int num)
int db_query_get_tuple_value(DB_QUERY_RESULT *result, int index, DB_VALUE *value)
Definition: db_query.c:2873
#define ER_AU_AUTHORIZATION_FAILURE
Definition: error_code.h:220
#define ER_AU_CANT_UPDATE
Definition: error_code.h:212
MOP sm_find_class(const char *name)
static int update_cache(MOP classop, SM_CLASS *sm_class, AU_CLASS_CACHE *cache)
void au_change_trigger_owner_method(MOP obj, DB_VALUE *returnval, DB_VALUE *trigger, DB_VALUE *owner)
int au_delete_auth_of_dropping_table(const char *class_name)
#define MSGCAT_AUTH_ROOT_USERS
Definition: authenticate.c:96
#define OID_ISNULL(oidp)
Definition: oid.h:81
int locator_is_class(MOP mop, DB_FETCH_MODE hint_purpose)
Definition: locator_cl.c:239
static DB_OBJECT * Au_authorizations_class
Definition: authenticate.c:374
#define LANG_SYS_CODESET
char * ws_copy_string(const char *str)
Definition: work_space.c:3457
#define ER_AU_NOT_ALLOW_TO_DROP_ACTIVE_USER
Definition: error_code.h:1531
#define ER_AU_INDEX_FAILURE
Definition: error_code.h:226
DB_OBJECT * user
Definition: authenticate.c:245
int db_set_drop(DB_SET *set, DB_VALUE *value)
Definition: db_set.c:530
bool locator_is_root(MOP mop)
Definition: locator_cl.c:212
#define ER_AU_NO_AUTHORIZATION
Definition: error_code.h:217
static int Au_cache_increment
Definition: authenticate.c:409
DB_SET * grants
Definition: authenticate.c:202
const char * au_user_name(void)
CLASS_USER * users
Definition: authenticate.c:290
static void map_grant_list(AU_GRANT *grants, MOP grantor)
#define ER_AU_NO_GRANT_OPTION
Definition: error_code.h:211
int smt_add_class_method(SM_TEMPLATE *template_, const char *name, const char *function)
static int au_delete_new_auth(MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type)
int db_compile_statement_local(DB_SESSION *session)
Definition: db_vdb.c:510
void au_init(void)
#define DB_CURSOR_END
Definition: dbtype_def.h:167
MOP do_get_serial_obj_id(DB_IDENTIFIER *serial_obj_id, DB_OBJECT *serial_class_mop, const char *serial_name)
#define GRANT_ENTRY_LENGTH
Definition: authenticate.c:130
#define DB_MAX_USER_LENGTH
Definition: dbtype_def.h:498
int db_compile_and_execute_local(const char *CSQL_query, void *result, DB_QUERY_ERROR *query_error)
Definition: db_vdb.c:3068
int au_drop_user(MOP user)
MOBJ vid_upd_instance(MOP mop)
static int au_change_serial_owner(MOP *object, MOP new_owner)
static void encrypt_password_sha1(const char *pass, int add_prefix, char *dest)
#define ER_SM_INVALID_CLASS
Definition: error_code.h:365
static bool match_password(const char *user, const char *database)
static void au_free_class_cache(AU_CLASS_CACHE *cache)
Definition: authenticate.c:742
static AU_CLASS_CACHE * Au_class_caches
Definition: authenticate.c:393
static int au_find_user_cache_index(DB_OBJECT *user, int *index, int check_it)
Definition: authenticate.c:894
static int au_add_direct_groups(DB_SET *new_groups, DB_VALUE *value)
int Au_disable
Definition: authenticate.c:309
const char * AU_AUTH_CLASS_NAME
Definition: authenticate.c:109
#define ER_OBJ_INVALID_TEMP_OBJECT
Definition: error_code.h:302
int au_fetch_class_force(MOP op, SM_CLASS **class_, AU_FETCHMODE fetchmode)
int au_set_user_comment(MOP user, const char *comment)
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
#define ER_AU_EXECUTE_FAILURE
Definition: error_code.h:227
#define ER_AU_CANT_ALTER_OWNER_OF_SYSTEM_CLASS
Definition: error_code.h:1464
int grant_option
Definition: authenticate.c:205
#define ER_IS_ABORTED_DUE_TO_DEADLOCK(err)
int db_add_constraint(MOP classmop, DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name, const char **att_names, int class_attributes)
Definition: db_class.c:1777
struct au_class_cache * next
Definition: authenticate.c:226
int intl_identifier_upper(const char *src, char *dst)
int crypt_encrypt_sha1_printable(const char *line, char *crypt, int maxlen)
Definition: encryption.c:200
int sc_set_current_schema(MOP user)
static int au_insert_new_auth(MOP grantor, MOP user, MOP class_mop, DB_AUTH auth_type, int grant_option)
#define ER_AU_MISSING_OR_INVALID_USER
Definition: error_code.h:230
#define MSGCAT_AUTH_USER_NAME2
Definition: authenticate.c:93
static void flush_caches(void)
void au_login_method(MOP class_mop, DB_VALUE *returnval, DB_VALUE *user, DB_VALUE *password)
unsigned is_vid
Definition: work_space.h:148
#define ER_QPROC_CANNOT_UPDATE_SERIAL
Definition: error_code.h:969
static int au_set_password_internal(MOP user, const char *password, int encode, char encrypt_prefix)
DB_COLLECTION * set_create_basic(void)
Definition: set_object.c:2407
#define AU_MAX_COMMENT_CHARS
Definition: authenticate.h:145
int sm_update_class(SM_TEMPLATE *template_, MOP *classmop)
unsigned int flags
Definition: class_object.h:762
void au_drop_member_method(MOP user, DB_VALUE *returnval, DB_VALUE *memval)