/* Copyright (C) 2000,2001,2002 Manuel Amador (Rudd-O) This file is part of Directory administrator. Directory administrator is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Directory administrator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Directory administrator; if not, send e-mail to amador@alomega.com */ #include "charset.h" #include #include #include "appsupport.h" #include "groups.h" #include "charset.h" #include "dir_entry.h" #include "appglobals.h" #include "appfunctions.h" ///TODAS LAS FUNCIONES RETORNAN REFERENCIAS A SUS ETRUCTURAS INTERNAS, PERO SACAN ///COPIAS DE LOS STRINGS PASADOS PARA GUARDARLOS. ESTOS DATOS SE DESTRUYEN AL LLAMAR ///A LAS FUNCIONES DESTROY ///OTROS TIPOS DE ESTRUCTURAS COMO LISTAS, NO SE COPIAN, SOLO SE GUARDAN REFERENCIAS gchar *group_handled_objectclasses[] = { "top","groupOfNames","posixGroup", NULL }; void g_debug_free (gpointer data) { g_print ("\ng_debug_free: freeing element containing %s\n",(char*)data); g_free (data); } diradmin_group * diradmin_group_new (gchar * dn, gchar * cn, gchar * gidnumber) { diradmin_group *conn = NULL; conn = g_new (diradmin_group, 1); conn->diradmin_group_data = NULL; conn->diradmin_group_members = NULL; conn->diradmin_group_dnmembers = NULL; conn->diradmin_group_objectclasses = NULL; diradmin_group_set_attribute (conn, "dn", cn); diradmin_group_set_attribute (conn, "cn", cn); diradmin_group_set_attribute (conn, "gidnumber", gidnumber); diradmin_group_set_members (conn, NULL); diradmin_group_set_dnmembers (conn, NULL); conn->diradmin_group_objectclasses = g_list_append (conn->diradmin_group_objectclasses, g_strdup ("top")); conn->diradmin_group_objectclasses = g_list_append (conn->diradmin_group_objectclasses, g_strdup ("posixGroup")); return conn; } diradmin_group * diradmin_group_duplicate (diradmin_group * tobeduped) { diradmin_group *conn = NULL; g_assert(tobeduped); conn = g_new (diradmin_group, 1); conn->diradmin_group_data = NULL; conn->diradmin_group_members = NULL; conn->diradmin_group_dnmembers = NULL; conn->diradmin_group_data = pairs_list_duplicate (tobeduped->diradmin_group_data); if (tobeduped->diradmin_group_members) diradmin_group_set_members (conn, tobeduped->diradmin_group_members); if (tobeduped->diradmin_group_dnmembers) diradmin_group_set_dnmembers (conn, tobeduped->diradmin_group_dnmembers); return conn; } void diradmin_group_destroy (diradmin_group * todestroy) { if (todestroy) { pairs_list_destroy (todestroy->diradmin_group_data); diradmin_group_set_members (todestroy, NULL); diradmin_group_set_dnmembers (todestroy, NULL); g_free (todestroy); } } gchar * diradmin_group_get_attribute (diradmin_group * conn, gchar * attr) { // return "hola"; g_assert (conn); g_assert (conn->diradmin_group_data); g_assert (attr); return pairs_list_get_attribute (conn->diradmin_group_data, attr); } void diradmin_group_set_attribute (diradmin_group * conn, gchar * attr, gchar * to) { g_assert (attr); conn->diradmin_group_data = pairs_list_set_attribute (conn->diradmin_group_data, attr, to); } void diradmin_group_remove_attribute (diradmin_group * conn, gchar * attr) { conn->diradmin_group_data = pairs_list_remove_attribute (conn->diradmin_group_data, attr); } GList * diradmin_group_get_members (diradmin_group * conn) { //return a reference to the members list. shouldnt be manipulated outside. return g_list_first (conn->diradmin_group_members); } GList * diradmin_group_get_dnmembers (diradmin_group * conn) { //return a reference to the members list. shouldnt be manipulated outside. return g_list_first (conn->diradmin_group_dnmembers); } void diradmin_group_add_member (diradmin_group * conn, gchar * member) { dir_entry* userDN = NULL; diradmin_group_remove_member (conn, member); conn->diradmin_group_members = g_list_append (conn->diradmin_group_members, g_strdup (member)); userDN = dir_entry_list_getbyuid (cached_dir_entries, member); if (userDN) { g_assert(dir_entry_get_dn(userDN)); diradmin_group_add_dnmember(conn,dir_entry_get_dn(userDN)); } } void diradmin_group_add_dnmember (diradmin_group * conn, gchar * member) { g_assert(member); diradmin_group_remove_dnmember (conn, member); conn->diradmin_group_dnmembers = g_list_append (conn->diradmin_group_dnmembers, g_strdup (member)); diradmin_group_add_objectclass (conn, "groupOfNames"); } /*void diradmin_group_dump_dnmembers(diradmin_group*conn) { GList* loopix; g_print("DN member dump of %s:\n",diradmin_group_get_attribute(conn,"dn")); for (loopix=g_list_first(conn->diradmin_group_members);loopix;loopix=loopix->next) { g_print(" Member: %s\n",loopix->data); } } void diradmin_group_dump_members(diradmin_group*conn) { GList* loopix; g_print("Unix member dump of %s:\n",diradmin_group_get_attribute(conn,"dn")); for (loopix=g_list_first(conn->diradmin_group_members);loopix;loopix=loopix->next) { g_print(" Member: %s\n",loopix->data); } } */ void diradmin_group_remove_member (diradmin_group * conn, gchar * member) { GList *iterator = NULL; dir_entry* userDN; iterator = g_list_find_custom (conn->diradmin_group_members, member, (GCompareFunc) g_strcasecmp); if (iterator) { conn->diradmin_group_members = g_list_remove_link (conn->diradmin_group_members, iterator); g_free (iterator->data); g_list_free_1 (iterator); } userDN = dir_entry_list_getbyuid (cached_dir_entries, member); if (userDN) { g_assert(dir_entry_get_dn(userDN)); diradmin_group_add_dnmember(conn,dir_entry_get_dn(userDN)); } } void diradmin_group_remove_dnmember (diradmin_group * conn, gchar * member) { GList *iterator = NULL; g_assert(member); iterator = g_list_find_custom (conn->diradmin_group_dnmembers, member, (GCompareFunc) g_strcasecmp); if (iterator) { conn->diradmin_group_dnmembers = g_list_remove_link (conn->diradmin_group_dnmembers, iterator); g_free (iterator->data); g_list_free_1 (iterator); } if (g_list_length (conn->diradmin_group_dnmembers) == 0) diradmin_group_remove_objectclass (conn, "groupOfNames"); } gboolean diradmin_group_has_member (diradmin_group * conn, gchar * allowedserver) { gchar *data; GList *iterator = NULL; iterator = g_list_first (conn->diradmin_group_members); while (iterator) { data = iterator->data; if (strcmp(allowedserver, iterator->data) == 0) { return (TRUE); } iterator = g_list_next (iterator); } return (FALSE); } gboolean diradmin_group_has_dnmember (diradmin_group * conn, gchar * allowedserver) { gchar *data; GList *iterator = NULL; iterator = g_list_first (conn->diradmin_group_dnmembers); while (iterator) { data = iterator->data; if (g_strcasecmp (allowedserver, iterator->data) == 0) { return (TRUE); } iterator = g_list_next (iterator); } return (FALSE); } void diradmin_group_set_members (diradmin_group * conn, GList * memberlist) { //removes all memberss in the list. that means frees its allocated storage. GList *newmembers = NULL; GList *members = NULL; //free the old members list members = g_list_first (diradmin_group_get_members (conn)); while (members) { g_free (members->data); members = g_list_next (members); } g_list_free (g_list_first (diradmin_group_get_members (conn))); //make a copy of the passed members list into newmembers members = g_list_first (memberlist); while (members) { newmembers = g_list_append (newmembers, g_strdup (members->data)); members = g_list_next (members); } conn->diradmin_group_members = newmembers; } void diradmin_group_set_dnmembers (diradmin_group * conn, GList * memberlist) { //removes all memberss in the list. that means frees its allocated storage. GList *newmembers = NULL; GList *members = NULL; //free the old members list members = g_list_first (diradmin_group_get_dnmembers (conn)); while (members) { g_free (members->data); members = g_list_next (members); } g_list_free (g_list_first (diradmin_group_get_dnmembers (conn))); //make a copy of the passed members list into newmembers members = g_list_first (memberlist); while (members) { newmembers = g_list_append (newmembers, g_strdup (members->data)); members = g_list_next (members); } conn->diradmin_group_dnmembers = newmembers; } //objectclasses GList * diradmin_group_get_objectclasses (diradmin_group * conn) { //return a reference to the allowedservers list. shouldnt be manipulated outside. return g_list_first (conn->diradmin_group_objectclasses); } void diradmin_group_add_objectclass (diradmin_group * conn, gchar * allowedserver) { int i; // gboolean si = FALSE; diradmin_group_remove_objectclass (conn, allowedserver); for (i = 0;group_handled_objectclasses[i];i++) { if (g_strcasecmp(group_handled_objectclasses[i],allowedserver) == 0) conn->diradmin_group_objectclasses = g_list_append (conn->diradmin_group_objectclasses, g_strdup (allowedserver)); } } void diradmin_group_remove_objectclass (diradmin_group * conn, gchar * allowedserver) { GList *iterator = NULL; for (iterator = g_list_first(conn->diradmin_group_objectclasses);iterator;iterator=iterator->next) if (g_strcasecmp(iterator->data,allowedserver)==0) { conn->diradmin_group_objectclasses = g_list_remove_link (conn->diradmin_group_objectclasses, iterator); g_free (iterator->data); g_list_free_1 (iterator); iterator =g_list_first(conn->diradmin_group_objectclasses); } } gboolean diradmin_group_has_objectclass (diradmin_group * conn, gchar * allowedserver) { gchar *data; GList *iterator = NULL; iterator = g_list_first (conn->diradmin_group_objectclasses); while (iterator) { data = iterator->data; if (g_strcasecmp (allowedserver, iterator->data) == 0) { return (TRUE); } iterator = g_list_next (iterator); } return (FALSE); } void diradmin_group_set_objectclasses (diradmin_group * conn, GList * allowedserverlist) { //removes all allowedservers in the list. that means frees its allocated storage. GList *newallowedservers = NULL; GList *allowedservers = NULL; //free the old allowedservers list allowedservers = g_list_first (diradmin_group_get_objectclasses (conn)); while (allowedservers) { g_free (allowedservers->data); allowedservers = g_list_next (allowedservers); } g_list_free (g_list_first (conn->diradmin_group_objectclasses)); //make a copy of the passed allowedservers list into newallowedservers allowedservers = g_list_first (allowedserverlist); while (allowedservers) { newallowedservers = g_list_append (newallowedservers, g_strdup (allowedservers->data)); allowedservers = g_list_next (allowedservers); } conn->diradmin_group_objectclasses = newallowedservers; } diradmin_group * diradmin_group_new_from_ldap (connection_profile * usethisone, char *userdn) { //conn should already be connected, or else undefined behaviour!!! diradmin_group *user = NULL; int ldap_errors; LDAPMessage *searchresults = NULL; LDAPMessage *entry = NULL; char **value_collection = NULL; gchar *filter; gchar *locale_attr; gchar *attribute; BerElement *attributehandler; int i = 0; user = g_new (diradmin_group, 1); user->diradmin_group_data = NULL; user->diradmin_group_members = NULL; user->diradmin_group_dnmembers = NULL; user->diradmin_group_objectclasses = NULL; //check 4 connection g_assert (connection_profile_get_ldap_handler (usethisone)); filter = "objectclass=*"; //look data up ldap_errors = ldap_search_s (connection_profile_get_ldap_handler (usethisone), userdn, LDAP_SCOPE_BASE, filter, NULL, 0, &searchresults); if (ldap_errors) { //any error? g_print ("LDAP error while creating a diradmin_group structure for "); g_print (userdn); g_print (": "); g_print (ldap_err2string (ldap_errors)); g_print ("\n"); //ldap_msgfree (searchresults); if (ldap_errors == LDAP_SERVER_DOWN) { connection_profile_invalidate(usethisone); } return NULL; } else { //get only first entry entry = ldap_first_entry (connection_profile_get_ldap_handler (usethisone), searchresults); // loop thru attribute values diradmin_group_set_attribute (user, "dn", userdn); attribute = ldap_first_attribute (connection_profile_get_ldap_handler (usethisone), entry, &attributehandler); g_assert (attribute); while (attribute) { value_collection = ldap_get_values (connection_profile_get_ldap_handler (usethisone), entry, attribute); //g_print ("%s = %s\n", attribute, value_collection[0]); if (g_strcasecmp (attribute, "objectClass") == 0) { for (i = 0;value_collection[i];i++) { //g_print (" adding objectclass %s\n", value_collection[i]); diradmin_group_add_objectclass (user, value_collection[i]); } } else if (g_strcasecmp (attribute, "memberUid") == 0) { for (i = 0;value_collection[i];i++) { locale_attr = convert_from_utf8 (value_collection[i]); //g_print (" adding member%s\n", value_collection[i]); user->diradmin_group_members = g_list_append(user->diradmin_group_members,g_strdup(locale_attr)); g_free(locale_attr); } } else if (g_strcasecmp (attribute, "member") == 0) { for (i = 0;value_collection[i];i++) { locale_attr = convert_from_utf8 (value_collection[i]); //g_print (" adding DN member%s\n", value_collection[i]); diradmin_group_add_dnmember (user, locale_attr); g_free(locale_attr); } } else { for (i = 0; value_collection[i]; i++) { g_assert (value_collection[0]); locale_attr = convert_from_utf8 (value_collection[0]); diradmin_group_set_attribute (user, attribute,locale_attr ); g_free(locale_attr); } } ldap_value_free (value_collection); attribute = ldap_next_attribute (connection_profile_get_ldap_handler (usethisone), entry, attributehandler); } ldap_msgfree (searchresults); } return (user); } gchar * gidnumber_to_cn (connection_profile * usethisone, gchar * gidnumber) { //user is responsible to free the returned string LDAPMessage *results = NULL; LDAPMessage *entry = NULL; char **value_collection; int ldap_errors; gchar *filter; gchar *attributetoreturn[2]; gchar *toreturn = NULL; if (connection_profile_is_connected (usethisone) == FALSE) { g_print ("NOT CONNECTED!!!! - returning! (while finding out gidnumber_to_cn\n"); return (NULL); } filter = g_strconcat ("(&(objectClass=posixGroup)(gidnumber=", gidnumber, "))", NULL); attributetoreturn[0] = "cn"; attributetoreturn[1] = NULL; //debug: g_print(filter); //look data up ldap_errors = ldap_search_s (connection_profile_get_ldap_handler (usethisone), connection_profile_get_treeroot (usethisone), LDAP_SCOPE_SUBTREE, filter, attributetoreturn, 0, &results); if (ldap_errors) { //any error? g_print ("LDAP error on gidnumber_to_cn: "); g_print (ldap_err2string (ldap_errors)); g_print ("\n"); toreturn = NULL; } else { g_assert (results); entry = ldap_first_entry (connection_profile_get_ldap_handler (usethisone), results); if (entry == NULL) { //any error? g_print ("\n"); g_print ("No posix groups available for translating gid to group name"); g_print ("\n"); toreturn = NULL; } else { value_collection = ldap_get_values (connection_profile_get_ldap_handler (usethisone), entry, "cn"); g_assert (value_collection); toreturn = g_strdup (value_collection[0]); ldap_value_free (value_collection); } ldap_msgfree (results); } g_free (filter); return (toreturn); } gchar * cn_to_gidnumber (connection_profile * usethisone, gchar * cn) { //user is responsible to free the returned string LDAPMessage *results = NULL; LDAPMessage *entry = NULL; char **value_collection; int ldap_errors; gchar *filter; gchar *attributetoreturn[2]; gchar *toreturn = NULL; gchar * utf8d_attr = NULL; utf8d_attr = convert_to_utf8(cn); if (connection_profile_is_connected (usethisone) == FALSE) { g_print ("NOT CONNECTED!!!! - returning! (while finding out gidnumber_to_cn\n"); return (NULL); } filter = g_strconcat ("(&(objectClass=posixGroup)(cn=", utf8d_attr, "))", NULL); attributetoreturn[0] = "gidnumber"; attributetoreturn[1] = NULL; //g_print(filter); //look data up ldap_errors = ldap_search_s (connection_profile_get_ldap_handler (usethisone), connection_profile_get_treeroot (usethisone), LDAP_SCOPE_SUBTREE, filter, attributetoreturn, 0, &results); if (ldap_errors) { //any error? g_print ("LDAP error on cn_to_gidnumber: "); g_print (ldap_err2string (ldap_errors)); g_print ("\n"); toreturn = NULL; } else { g_assert (results); entry = ldap_first_entry (connection_profile_get_ldap_handler (usethisone), results); if (entry == NULL) { //any error? g_print ("No posix groups available for translating gid to group name: "); g_print ("\n"); toreturn = NULL; } else { value_collection = ldap_get_values (connection_profile_get_ldap_handler (usethisone), entry, "gidnumber"); g_assert (value_collection); toreturn = g_strdup (value_collection[0]); ldap_value_free (value_collection); } ldap_msgfree (results); } g_free (filter); g_free (utf8d_attr); return (toreturn); } ldaptransaction* diradmin_group_generate_ldapdiff (diradmin_group * oldone, diradmin_group * newone) { ldaptransaction *t; gchar **values; gchar *attrs2chk[] = { "gidnumber","cn",NULL }; GList *l = NULL; gint acnt; g_assert (oldone); g_assert (newone); t = ldaptransaction_new(); for (acnt=0;attrs2chk[acnt];acnt++) { if (g_strcasecmp (attrs2chk[acnt], "groupPassword") != 0 && diradmin_group_get_attribute (newone, attrs2chk [acnt]) == NULL) ldaptransaction_delete(t,attrs2chk[acnt],NULL); else if (diradmin_group_get_attribute (oldone, attrs2chk[acnt]) == NULL && diradmin_group_get_attribute (newone, attrs2chk [acnt]) != NULL) { values = g_new0 (gchar *, 2); values[0] = convert_to_utf8( diradmin_group_get_attribute (newone, attrs2chk[acnt])); ldaptransaction_replace(t, attrs2chk[acnt],values); } else if (strcmp (diradmin_group_get_attribute (oldone, attrs2chk[acnt]), diradmin_group_get_attribute (newone, attrs2chk [acnt])) != 0) { values = g_new0 (gchar *, 2); values[0] = convert_to_utf8( /* g_strdup (*/diradmin_group_get_attribute (newone, attrs2chk[acnt])); ldaptransaction_replace(t,attrs2chk[acnt],values); } } for (l = diradmin_group_get_objectclasses (oldone);l;l=g_list_next(l)) if (diradmin_group_has_objectclass (newone, l->data) == FALSE) { //generar mod de eliminacion values = g_new0 (gchar *, 2); values[0] = g_strdup (l->data); ldaptransaction_delete(t,"objectClass",values); } for (l = diradmin_group_get_objectclasses (newone);l;l=g_list_next(l)) if (diradmin_group_has_objectclass (oldone, l->data) == FALSE) { //generar mod de eliminacion values = g_new0 (gchar *, 2); values[0] = g_strdup (l->data); ldaptransaction_add(t,"objectClass",values); } for (l = diradmin_group_get_members (oldone);l;l=g_list_next(l)) if (diradmin_group_has_member (newone, l->data) == FALSE) { //generar mod de eliminacion values = g_new0 (gchar *, 2); values[0] = convert_to_utf8( l->data); ldaptransaction_delete(t,"memberUid",values); } for (l = diradmin_group_get_members (newone);l;l=g_list_next(l)) if (diradmin_group_has_member (oldone, l->data) == FALSE) { //generar mod de adicion values = g_new0 (gchar *, 2); values[0] = convert_to_utf8( l->data); ldaptransaction_add(t,"memberUid",values); } for (l = diradmin_group_get_dnmembers (oldone);l;l=g_list_next(l)) if (diradmin_group_has_dnmember (newone, l->data) == FALSE) { //generar mod de eliminacion values = g_new0 (gchar *, 2); values[0] = convert_to_utf8( l->data); ldaptransaction_delete(t,"member",values); } for (l = diradmin_group_get_dnmembers (newone);l;l=g_list_next(l)) if (diradmin_group_has_dnmember (oldone, l->data) == FALSE) { //generar mod de adicion values = g_new0 (gchar *, 2); values[0] = convert_to_utf8( l->data); ldaptransaction_add(t,"member",values); } return t; } diradmin_group * create_group_struct_from_dialogbox (connection_profile * conn, GtkWidget * dialogbox, gchar * dn) { diradmin_group *newgroup; gint iterator; gchar *cn = NULL; gchar *gidnumber = NULL; GtkCList *members = NULL; gchar *member = NULL; gchar *membertype = NULL; gchar*membercn = NULL; GList *listone; dir_entry*memberentry; gint thisgidnumber; members = (GtkCList *) lookup_widget (dialogbox, "members"); cn = gtk_entry_get_text (GTK_ENTRY (lookup_widget (dialogbox, "cn"))); gidnumber = gtk_entry_get_text (GTK_ENTRY (lookup_widget (dialogbox, "gidnumber"))); thisgidnumber = atoi(gidnumber); newgroup = diradmin_group_new (dn, cn, gidnumber); for (iterator = 0; iterator < members->rows; iterator++) { member = gtk_clist_get_row_data(members,iterator); gtk_clist_get_text (members, iterator, 0, &membertype); //handle case donde se cambia el primary group y despues recien se da click en add members memberentry = cached_dir_entries_getbydn(member); if (memberentry && g_strcasecmp(membertype,"Primary") == 0 && memberentry->gidnumber != thisgidnumber) { g_print(" User %s is no longer primary, dropping\n",member); } else { g_print(" Appending to dnmembers %s member %s\n",membertype,member); diradmin_group_add_dnmember (newgroup, member); } //solo si el usuario existe todavia en la base de datos! if (memberentry && dir_entry_is_user(memberentry)) { if (g_strcasecmp(membertype,"Secondary") == 0) { membercn = dir_entry_get_uid(memberentry); g_print(" Appending to members %s member %s\n",membertype,membercn); diradmin_group_add_member(newgroup,membercn); } } } listone = diradmin_group_get_objectclasses (newgroup); while (listone) { g_print (listone->data); listone = listone->next; } return (newgroup); } ldaptransaction * diradmin_group_create_ldapdiff (diradmin_group * newone) { ldaptransaction * t; gchar *attrs2chk[] = {"cn", "gidnumber", NULL}; GList *l = NULL; gint acnt = 0; dir_entry *userDN = NULL; gchar **values; g_assert (newone); t = ldaptransaction_new(); values = g_new0 (gchar *, 7); values[0] = g_strdup ("top"); values[1] = g_strdup ("posixGroup"); if (g_list_length (diradmin_group_get_members (newone))) values[2] = g_strdup ("groupOfNames"); ldaptransaction_add(t,"objectclass",values); for(acnt=0;attrs2chk[acnt];acnt++) { if (diradmin_group_get_attribute (newone, attrs2chk[acnt]) != NULL) { values = g_new0 (gchar *, 2); values[0] = convert_to_utf8 (diradmin_group_get_attribute(newone, attrs2chk[acnt])); ldaptransaction_add(t,attrs2chk[acnt],values); } } if (g_list_length (diradmin_group_get_members (newone))) { values = g_new0 (gchar *, 2 + g_list_length(diradmin_group_get_members (newone))); acnt = 0; for(l = diradmin_group_get_members (newone);l;l=g_list_next(l)) { values[acnt] = convert_to_utf8( l->data); acnt++; } ldaptransaction_add(t,"memberUid",values); /* Generating DN list for groupOfNames */ values = g_new0 (gchar *, 2 + g_list_length(diradmin_group_get_members (newone))); acnt = 0; for (l = diradmin_group_get_members (newone);l;l=g_list_next(l)) { userDN = dir_entry_list_getbyuid (cached_dir_entries, l->data); if (userDN) { g_print ("\n\n\n\n\n\n\n%s",dir_entry_get_dn(userDN)); values[acnt] = g_strdup(dir_entry_get_dn(userDN)); acnt++; } } ldaptransaction_add(t,"member",values); } return t; }