/* ADD SOMEONE (USER OR GROUP) TO A GROUP */ void tool_addtoGroup(int argc, char *argv[]) { char *s; long arg1, arg2; if (check_args_num(argc, 3)) { printf( "Usage: ag group user\ngroup\t\t" "id or name of group to add to\nuser\t\t" "id or name of user to add\n"); return; } arg1 = get_id(argv[1]); PDB_lookupById((int32_t)arg1, &s); if (!PDB_ISGROUP(arg1) || s == NULL) { printf("No group %s found!\n", argv[1]); if (s) free(s); return; } free(s); arg2 = get_id(argv[2]); PDB_lookupById((int32_t)arg2, &s); if (s == NULL) { printf("No user or group %s found!\n", argv[2]); if (s) free(s); return; } free(s); PDB_addToGroup(arg2, arg1); }
/* CREATE NEW USER WITH ID*/ void tool_newUser_Id(int argc, char *argv[]) { char *s; int32_t id; int32_t arg2; if (check_args_num(argc, 3)) { printf( "Usage: nui name id\nname\t\t" "name of new user\nid\t\tid of new user\n"); return; } arg2 = atoi(argv[2]); if (!PDB_ISUSER(arg2)) { printf("Not a valid user-id (it needs to be > 0).\n"); return; } PDB_lookupById((int32_t)arg2, &s); if (s != NULL) { printf("ID alread used by \"%s\".\n", s); free(s); return; } PDB_createUser(argv[1], &id); if (id == 0) { printf("Failed to creat user.\n"); return; } if (id != arg2) PDB_changeId(id, arg2); }
/* Translates Id and returns the corresponding username or groupname in Name. Returns 0 on success, -1 if Id is not translatable. */ int AL_IdToName(IN int Id, OUT char *Name) { char *tmp; LogMsg(1, AL_DebugLevel, stdout, "in AL_IdToName(%d)", Id); if(Id==0) return -1; PDB_lookupById((int32_t) Id, &tmp); if(tmp != NULL){ strcpy(Name,tmp); free(tmp); return 0; } return -1; }
/* DELETE USER OR GROUP */ void tool_delete(int argc, char *argv[]) { char *s; long arg1; if (check_args_num(argc, 2)) { printf( "Usage: d id/name\n" "id/name\t\tid or name of user/group\n"); return; } arg1 = get_id(argv[1]); PDB_lookupById((int32_t)arg1, &s); if (s == NULL) { printf("%s not found!\n", argv[1]); return; } free(s); if (PDB_ISGROUP(arg1)) PDB_deleteGroup(arg1); else PDB_deleteUser(arg1); }
/* CREATE NEW GROUP */ void tool_newGroup(int argc, char *argv[]) { char *s; int32_t id; int32_t arg2; if (check_args_num(argc, 3)) { printf( "Usage: ng name owner\nname\t\t" "name of new group\nowner\t\t" "id/name number of group owner\n"); return; } arg2 = get_id(argv[2]); PDB_lookupById((int32_t)arg2, &s); if (!PDB_ISUSER(arg2) || s == NULL) { printf("Owner must be a valid username/id, %s not found!\n", argv[2]); if (s) free(s); return; } free(s); PDB_createGroup(argv[1], arg2, &id); }
void tool_import(int argc, char *argv[]) { FILE *userfile, *groupfile; char user[64], group[64], owner[64], member[64], *s; int32_t user_id, group_id, owner_id, member_id, create_id; int rc; if (check_args_num(argc, 3)) { fprintf(stderr, "Usage: import <userfile> <groupfile>\n"); return; } userfile = fopen(argv[1], "r"); if (!userfile) { fprintf(stderr, "Can't open userfile '%s'\n", argv[1]); return; } groupfile = fopen(argv[2], "r"); if (!groupfile) { fprintf(stderr, "Can't open groupfile '%s'\n", argv[2]); return; } /* recreate all users */ while (1) { rc = fscanf(userfile, "%[^:]:%*[^:]:%d:%*[^\n]\n", user, &user_id); if (rc != 2) break; if (user_id == 0) { printf("Userid 0 must be avoided, skipping entry for %s\n", user); continue; } if (user_id < 0) { printf("Skipping user %s with a negative id %d\n", user, user_id); continue; } /* create user */ PDB_lookupById(user_id, &s); if (s) { printf("Duplicate user for id %d, found both %s and %s\n", user_id, s, user); free(s); continue; } PDB_createUser(user, &create_id); PDB_changeId(create_id, user_id); printf("Created user %s, id %d\n", user, user_id); } fclose(userfile); /* recreate groups */ while (1) { int c; rc = fscanf(groupfile, "%[^:]:%*[^:]:%d:%[^,\n]", group, &group_id, owner); if (rc != 3) break; /* skip to the next newline */ do { c = fgetc(groupfile); } while (c != EOF && c != (int)'\n'); if (group_id == 0) { printf("Groupid 0 must be avoided, skipping entry for %s\n", group); continue; } /* restore the :'s in the group name */ s = group; while ((s = strchr(s, '%')) != NULL) *s = ':'; /* negate positive group ids, Coda groups are negative numbers */ if (group_id > 0) { group_id = -group_id; /* assuming this is the /etc/group file, force owner to System */ strcpy(owner, "System"); } /* create group */ PDB_lookupByName(owner, &owner_id); if (owner_id == 0) { printf("Group %s's owner %s cannot be found\n", group, owner); continue; } if (!PDB_ISUSER(owner_id)) { printf("Group %s's owner %s is a group but should be a user\n", group, owner); continue; } PDB_lookupById(group_id, &s); if (s) { printf("Duplicate group for id %d, found both %s and %s\n", group_id, s, group); free(s); continue; } PDB_createGroup(group, owner_id, &create_id); PDB_changeId(create_id, group_id); printf("Created group %s, id %d, owner %s\n", group, group_id, owner); } /* Add group members. Groups can be members of another group, so that is * why we needed to create all the groups first */ rewind(groupfile); while (1) { rc = fscanf(groupfile, "%[^:]:%*[^:]:%d:", group, &group_id); if (rc != 2) break; if (group_id == 0) continue; /* restore the :'s in the group name */ s = group; while ((s = strchr(s, '%')) != NULL) *s = ':'; if (group_id > 0) { group_id = -group_id; } else { /* skip the owner when the group_id is negative */ fscanf(groupfile, "%[^,\n]%*[,]", owner); } /* add group members */ printf("Adding members to %s\n\t", group); while (fscanf(groupfile, "%[^,\n]%*[,]", member) == 1) { /* restore the :'s in the name */ s = member; while ((s = strchr(s, '%')) != NULL) *s = ':'; PDB_lookupByName(member, &member_id); if (member_id == 0) { printf("\nGroup %s's member %s cannot be found\n\t", group, member); continue; } PDB_addToGroup(member_id, group_id); printf(" %s", member); } fgetc(groupfile); /* eat the '\n' */ printf("\n"); } fclose(groupfile); }
/* dump/restore database contents */ void tool_export(int argc, char *argv[]) { int32_t id, i; PDB_profile rec; PDB_HANDLE h; FILE *userfile, *groupfile; char *s; int rc; if (check_args_num(argc, 3)) { printf("Usage: export <userfile> <groupfile>\n"); return; } userfile = fopen(argv[1], "w"); groupfile = fopen(argv[2], "w"); h = PDB_db_open(O_RDONLY); while ((rc = PDB_db_nextkey(h, &id))) { if (rc == -1) continue; PDB_readProfile(h, id, &rec); { if (rec.id == 0) continue; if (PDB_ISUSER(rec.id)) { /* users are dumped in an /etc/passwd like format * "<username>:x:<userid>:500::/:" */ fprintf(userfile, "%s:*:%d:500::/:\n", rec.name, rec.id); } else { /* groups and group members are dumped in an /etc/group like * format "<groupname>:x:<groupid>:<owner>[,<members>]*" */ /* escape the :'s in the group names */ s = rec.name; while ((s = strchr(s, ':')) != NULL) *s = '%'; PDB_lookupById(rec.owner_id, &s); fprintf(groupfile, "%s:*:%d:%s", rec.name, rec.id, s); free(s); for (i = 0; i < rec.groups_or_members.size; i++) { if (rec.groups_or_members.data[i] == rec.owner_id) continue; PDB_lookupById(rec.groups_or_members.data[i], &s); if (s == NULL) continue; fprintf(groupfile, ",%s", s); free(s); } fprintf(groupfile, "\n"); } } PDB_freeProfile(&rec); } PDB_db_close(h); fclose(userfile); fclose(groupfile); }
/* dump/restore database contents */ void tool_ldif_export(int argc, char *argv[]) { int32_t id, i; PDB_profile rec; PDB_HANDLE h; FILE *ldiffile; char *s, *basedn; int rc, pass = 0; if (check_args_num(argc, 3)) { printf("Usage: ldif_export <ldif-file> <basedn>\n"); return; } ldiffile = fopen(argv[1], "w"); basedn = argv[2]; again: h = PDB_db_open(O_RDONLY); while ((rc = PDB_db_nextkey(h, &id))) { if (rc == -1) continue; PDB_readProfile(h, id, &rec); { if (rec.id == 0) continue; if (PDB_ISUSER(rec.id)) { /* skip users during the second pass */ if (pass == 1) continue; /* users are dumped as: * * dn: cn=<name>,$basedn * objectClass: top * objectClass: person * objectClass: organizationalPerson * objectClass: inetOrgPerson * objectClass: codaAccount * cn: <name> * uid: <username> * uidNumber: <userid> * * And we 'invent' 2 fields that are required by posixAccount, * gidNumber: 65535 * homeDirectory: /coda/<realm>/usr/<username> */ fprintf(ldiffile, "dn: cn=%s,%s\n" "objectClass: top\n" "objectClass: person\n" "objectClass: organizationalPerson\n" "objectClass: inetOrgPerson\n" "objectClass: posixAccount\n" "cn: %s\nuid: %s\nuidNumber: %d\n" "gidNumber: 65535\n" "homeDirectory: /coda/myrealm/usr/%s\n" "#mail: %s@mydomain\n\n", rec.name, basedn, rec.name, rec.name, rec.id, rec.name, rec.name); } else { /* skip groups during the first pass */ if (pass == 0) continue; /* groups and group members are dumped as follows: * * dn: cn=<groupname>,$basedn * objectClass: top * objectClass: groupOfNames * objectClass: posixGroup * cn: <groupname> * gidNumber: -<groupid> * owner: <ownerdn> * member: <member1dn> * member: <member2dn> * ... */ PDB_lookupById(rec.owner_id, &s); CODA_ASSERT(s != NULL); fprintf(ldiffile, "dn: cn=%s,%s\n" "objectClass: top\n" "objectClass: groupOfNames\n" "objectClass: posixGroup\n" "#description:\n" "cn: %s\ngidNumber: %d\nowner: %s,%s\n", rec.name, basedn, rec.name, -rec.id, s, basedn); free(s); for (i = 0; i < rec.groups_or_members.size; i++) { PDB_lookupById(rec.groups_or_members.data[i], &s); if (s == NULL) continue; fprintf(ldiffile, "member: cn=%s,%s\n", s, basedn); free(s); } fprintf(ldiffile, "\n"); } } PDB_freeProfile(&rec); } PDB_db_close(h); /* we make second pass to dump the groups after the users */ if (pass == 0) { pass = 1; goto again; } fclose(ldiffile); }