1/* 2 Samba Unix/Linux SMB client library 3 Distributed SMB/CIFS Server Management Utility 4 Copyright (C) 2003 Andrew Bartlett (abartlet@samba.org) 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#define FOO(x) (x) 21#include "includes.h" 22#include "utils/net.h" 23 24#define ALLOC_CHECK(mem) do { \ 25 if (!mem) { \ 26 d_fprintf(stderr, _("Out of memory!\n")); \ 27 talloc_free(ctx); \ 28 return -1; \ 29 } } while(0) 30 31/*********************************************************** 32 Helper function for net_idmap_dump. Dump one entry. 33 **********************************************************/ 34static int net_idmap_dump_one_entry(TDB_CONTEXT *tdb, 35 TDB_DATA key, 36 TDB_DATA data, 37 void *unused) 38{ 39 if (strcmp((char *)key.dptr, "USER HWM") == 0) { 40 printf(_("USER HWM %d\n"), IVAL(data.dptr,0)); 41 return 0; 42 } 43 44 if (strcmp((char *)key.dptr, "GROUP HWM") == 0) { 45 printf(_("GROUP HWM %d\n"), IVAL(data.dptr,0)); 46 return 0; 47 } 48 49 if (strncmp((char *)key.dptr, "S-", 2) != 0) 50 return 0; 51 52 printf("%s %s\n", data.dptr, key.dptr); 53 return 0; 54} 55 56/*********************************************************** 57 Dump the current idmap 58 **********************************************************/ 59static int net_idmap_dump(struct net_context *c, int argc, const char **argv) 60{ 61 TDB_CONTEXT *idmap_tdb; 62 63 if ( argc != 1 || c->display_usage) { 64 d_printf("%s\n%s", 65 _("Usage:"), 66 _("net idmap dump <inputfile>\n" 67 " Dump current ID mapping.\n" 68 " inputfile\tTDB file to read mappings from.\n")); 69 return c->display_usage?0:-1; 70 } 71 72 idmap_tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0); 73 74 if (idmap_tdb == NULL) { 75 d_fprintf(stderr, _("Could not open idmap: %s\n"), argv[0]); 76 return -1; 77 } 78 79 tdb_traverse(idmap_tdb, net_idmap_dump_one_entry, NULL); 80 81 tdb_close(idmap_tdb); 82 83 return 0; 84} 85 86/*********************************************************** 87 Write entries from stdin to current local idmap 88 **********************************************************/ 89 90static int net_idmap_restore(struct net_context *c, int argc, const char **argv) 91{ 92 TALLOC_CTX *ctx; 93 FILE *input; 94 95 if (c->display_usage) { 96 d_printf("%s\n%s", 97 _("Usage:"), 98 _("net idmap restore [inputfile]\n" 99 " Restore ID mappings from file\n" 100 " inputfile\tFile to load ID mappings from. If " 101 "not given, load data from stdin.\n")); 102 return 0; 103 } 104 105 if (! winbind_ping()) { 106 d_fprintf(stderr, 107 _("To use net idmap Winbindd must be running.\n")); 108 return -1; 109 } 110 111 ctx = talloc_new(NULL); 112 ALLOC_CHECK(ctx); 113 114 if (argc == 1) { 115 input = fopen(argv[0], "r"); 116 } else { 117 input = stdin; 118 } 119 120 while (!feof(input)) { 121 char line[128], sid_string[128]; 122 int len; 123 struct wbcDomainSid sid; 124 enum id_type type = ID_TYPE_NOT_SPECIFIED; 125 unsigned long idval; 126 wbcErr wbc_status; 127 128 if (fgets(line, 127, input) == NULL) 129 break; 130 131 len = strlen(line); 132 133 if ( (len > 0) && (line[len-1] == '\n') ) 134 line[len-1] = '\0'; 135 136 if (sscanf(line, "GID %lu %128s", &idval, sid_string) == 2) { 137 type = ID_TYPE_GID; 138 } else if (sscanf(line, "UID %lu %128s", &idval, sid_string) == 2) { 139 type = ID_TYPE_UID; 140 } else if (sscanf(line, "USER HWM %lu", &idval) == 1) { 141 /* set uid hwm */ 142 wbc_status = wbcSetUidHwm(idval); 143 if (!WBC_ERROR_IS_OK(wbc_status)) { 144 d_fprintf(stderr, 145 _("Could not set USER HWM: %s\n"), 146 wbcErrorString(wbc_status)); 147 } 148 continue; 149 } else if (sscanf(line, "GROUP HWM %lu", &idval) == 1) { 150 /* set gid hwm */ 151 wbc_status = wbcSetGidHwm(idval); 152 if (!WBC_ERROR_IS_OK(wbc_status)) { 153 d_fprintf(stderr, 154 _("Could not set GROUP HWM: %s\n"), 155 wbcErrorString(wbc_status)); 156 } 157 continue; 158 } else { 159 d_fprintf(stderr, _("ignoring invalid line [%s]\n"), 160 line); 161 continue; 162 } 163 164 wbc_status = wbcStringToSid(sid_string, &sid); 165 if (!WBC_ERROR_IS_OK(wbc_status)) { 166 d_fprintf(stderr, _("ignoring invalid sid [%s]: %s\n"), 167 sid_string, wbcErrorString(wbc_status)); 168 continue; 169 } 170 171 if (type == ID_TYPE_UID) { 172 wbc_status = wbcSetUidMapping(idval, &sid); 173 } else { 174 wbc_status = wbcSetGidMapping(idval, &sid); 175 } 176 if (!WBC_ERROR_IS_OK(wbc_status)) { 177 d_fprintf(stderr, 178 _("Could not set mapping of %s %lu to sid %s: %s\n"), 179 (type == ID_TYPE_GID) ? "GID" : "UID", 180 idval, sid_string, 181 wbcErrorString(wbc_status)); 182 continue; 183 } 184 } 185 186 if (input != stdin) { 187 fclose(input); 188 } 189 190 talloc_free(ctx); 191 return 0; 192} 193 194/*********************************************************** 195 Delete a SID mapping from a winbindd_idmap.tdb 196 **********************************************************/ 197static int net_idmap_delete(struct net_context *c, int argc, const char **argv) 198{ 199 d_printf("%s\n", _("Not implemented yet")); 200 return -1; 201} 202 203static int net_idmap_set(struct net_context *c, int argc, const char **argv) 204{ 205 d_printf("%s\n", _("Not implemented yet")); 206 return -1; 207} 208bool idmap_store_secret(const char *backend, bool alloc, 209 const char *domain, const char *identity, 210 const char *secret) 211{ 212 char *tmp; 213 int r; 214 bool ret; 215 216 if (alloc) { 217 r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend); 218 } else { 219 r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain); 220 } 221 222 if (r < 0) return false; 223 224 strupper_m(tmp); /* make sure the key is case insensitive */ 225 ret = secrets_store_generic(tmp, identity, secret); 226 227 free(tmp); 228 return ret; 229} 230 231 232static int net_idmap_secret(struct net_context *c, int argc, const char **argv) 233{ 234 TALLOC_CTX *ctx; 235 const char *secret; 236 const char *dn; 237 char *domain; 238 char *backend; 239 char *opt = NULL; 240 bool ret; 241 242 if (argc != 2 || c->display_usage) { 243 d_printf("%s\n%s", 244 _("Usage:"), 245 _("net idmap secret {<DOMAIN>|alloc} <secret>\n" 246 " Set the secret for the specified domain " 247 "(or alloc module)\n" 248 " DOMAIN\tDomain to set secret for.\n" 249 " alloc\tSet secret for the alloc module\n" 250 " secret\tNew secret to set.\n")); 251 return c->display_usage?0:-1; 252 } 253 254 secret = argv[1]; 255 256 ctx = talloc_new(NULL); 257 ALLOC_CHECK(ctx); 258 259 if (strcmp(argv[0], "alloc") == 0) { 260 domain = NULL; 261 backend = lp_idmap_alloc_backend(); 262 } else { 263 domain = talloc_strdup(ctx, argv[0]); 264 ALLOC_CHECK(domain); 265 266 opt = talloc_asprintf(ctx, "idmap config %s", domain); 267 ALLOC_CHECK(opt); 268 269 backend = talloc_strdup(ctx, lp_parm_const_string(-1, opt, "backend", "tdb")); 270 ALLOC_CHECK(backend); 271 } 272 273 if ( ( ! backend) || ( ! strequal(backend, "ldap"))) { 274 d_fprintf(stderr, 275 _("The only currently supported backend is LDAP\n")); 276 talloc_free(ctx); 277 return -1; 278 } 279 280 if (domain) { 281 282 dn = lp_parm_const_string(-1, opt, "ldap_user_dn", NULL); 283 if ( ! dn) { 284 d_fprintf(stderr, 285 _("Missing ldap_user_dn option for domain " 286 "%s\n"), domain); 287 talloc_free(ctx); 288 return -1; 289 } 290 291 ret = idmap_store_secret("ldap", false, domain, dn, secret); 292 } else { 293 dn = lp_parm_const_string(-1, "idmap alloc config", "ldap_user_dn", NULL); 294 if ( ! dn) { 295 d_fprintf(stderr, 296 _("Missing ldap_user_dn option for alloc " 297 "backend\n")); 298 talloc_free(ctx); 299 return -1; 300 } 301 302 ret = idmap_store_secret("ldap", true, NULL, dn, secret); 303 } 304 305 if ( ! ret) { 306 d_fprintf(stderr, _("Failed to store secret\n")); 307 talloc_free(ctx); 308 return -1; 309 } 310 311 d_printf(_("Secret stored\n")); 312 return 0; 313} 314 315int net_help_idmap(struct net_context *c, int argc, const char **argv) 316{ 317 d_printf(_("net idmap dump <inputfile>\n" 318 " Dump current id mapping\n")); 319 320 d_printf(_("net idmap restore\n" 321 " Restore entries from stdin\n")); 322 323 /* Deliberately *not* document net idmap delete */ 324 325 d_printf(_("net idmap secret <DOMAIN>|alloc <secret>\n" 326 " Set the secret for the specified DOMAIN (or the alloc " 327 "module)\n")); 328 329 return -1; 330} 331 332static int net_idmap_aclmapset(struct net_context *c, int argc, const char **argv) 333{ 334 TALLOC_CTX *mem_ctx; 335 int result = -1; 336 DOM_SID src_sid, dst_sid; 337 char *src, *dst; 338 struct db_context *db; 339 struct db_record *rec; 340 NTSTATUS status; 341 342 if (argc != 3 || c->display_usage) { 343 d_fprintf(stderr, "%s net idmap aclmapset <tdb> " 344 "<src-sid> <dst-sid>\n", _("Usage:")); 345 return -1; 346 } 347 348 if (!(mem_ctx = talloc_init("net idmap aclmapset"))) { 349 d_fprintf(stderr, _("talloc_init failed\n")); 350 return -1; 351 } 352 353 if (!(db = db_open(mem_ctx, argv[0], 0, TDB_DEFAULT, 354 O_RDWR|O_CREAT, 0600))) { 355 d_fprintf(stderr, _("db_open failed: %s\n"), strerror(errno)); 356 goto fail; 357 } 358 359 if (!string_to_sid(&src_sid, argv[1])) { 360 d_fprintf(stderr, _("%s is not a valid sid\n"), argv[1]); 361 goto fail; 362 } 363 364 if (!string_to_sid(&dst_sid, argv[2])) { 365 d_fprintf(stderr, _("%s is not a valid sid\n"), argv[2]); 366 goto fail; 367 } 368 369 if (!(src = sid_string_talloc(mem_ctx, &src_sid)) 370 || !(dst = sid_string_talloc(mem_ctx, &dst_sid))) { 371 d_fprintf(stderr, _("talloc_strdup failed\n")); 372 goto fail; 373 } 374 375 if (!(rec = db->fetch_locked( 376 db, mem_ctx, string_term_tdb_data(src)))) { 377 d_fprintf(stderr, _("could not fetch db record\n")); 378 goto fail; 379 } 380 381 status = rec->store(rec, string_term_tdb_data(dst), 0); 382 TALLOC_FREE(rec); 383 384 if (!NT_STATUS_IS_OK(status)) { 385 d_fprintf(stderr, _("could not store record: %s\n"), 386 nt_errstr(status)); 387 goto fail; 388 } 389 390 result = 0; 391fail: 392 TALLOC_FREE(mem_ctx); 393 return result; 394} 395 396/*********************************************************** 397 Look at the current idmap 398 **********************************************************/ 399int net_idmap(struct net_context *c, int argc, const char **argv) 400{ 401 struct functable func[] = { 402 { 403 "dump", 404 net_idmap_dump, 405 NET_TRANSPORT_LOCAL, 406 N_("Dump the current ID mappings"), 407 N_("net idmap dump\n" 408 " Dump the current ID mappings") 409 }, 410 { 411 "restore", 412 net_idmap_restore, 413 NET_TRANSPORT_LOCAL, 414 N_("Restore entries from stdin"), 415 N_("net idmap restore\n" 416 " Restore entries from stdin") 417 }, 418 { 419 "setmap", 420 net_idmap_set, 421 NET_TRANSPORT_LOCAL, 422 N_("Not implemented yet"), 423 N_("net idmap setmap\n" 424 " Not implemented yet") 425 }, 426 { 427 "delete", 428 net_idmap_delete, 429 NET_TRANSPORT_LOCAL, 430 N_("Not implemented yet"), 431 N_("net idmap delete\n" 432 " Not implemented yet") 433 }, 434 { 435 "secret", 436 net_idmap_secret, 437 NET_TRANSPORT_LOCAL, 438 N_("Set secret for specified domain"), 439 N_("net idmap secret {<DOMAIN>|alloc} <secret>\n" 440 " Set secret for specified domain or alloc module") 441 }, 442 { 443 "aclmapset", 444 net_idmap_aclmapset, 445 NET_TRANSPORT_LOCAL, 446 N_("Set acl map"), 447 N_("net idmap aclmapset\n" 448 " Set acl map") 449 }, 450 {NULL, NULL, 0, NULL, NULL} 451 }; 452 453 return net_run_function(c, argc, argv, "net idmap", func); 454} 455 456 457