pwenc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. #include <sys/socket.h>
  13. #include <sys/errno.h>
  14. #include <sys/param.h>
  15. #include <sys/types.h>
  16. #if defined(LINUX) /* I bet other Unix would like
  17. * this flag. But don't want to
  18. * break other builds so far */
  19. #include <unistd.h>
  20. #endif
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <stdlib.h>
  25. #include "ldap.h"
  26. #include "../slapi-plugin.h"
  27. #include "../slap.h"
  28. #include <nspr.h>
  29. #include <nss.h>
  30. #include "../../plugins/pwdstorage/pwdstorage.h"
  31. int ldap_syslog;
  32. int ldap_syslog_level;
  33. int slapd_ldap_debug = LDAP_DEBUG_ANY;
  34. int detached;
  35. FILE *error_logfp;
  36. FILE *access_logfp;
  37. struct pw_scheme *pwdhashscheme;
  38. int heflag = 0;
  39. static int slapd_config(const char *configdir, const char *configfile);
  40. static int entry_has_attr_and_value(Slapi_Entry *e, const char *attrname, char *value);
  41. static void
  42. usage( name )
  43. char *name;
  44. {
  45. fprintf( stderr, "usage: %s -D config-dir [-H] [-s scheme | -c comparepwd ] password...\n", name );
  46. exit( 1 );
  47. }
  48. /*
  49. * If global "heflag" is non-zero, un-hex-encode the string
  50. * and return a decoded copy. Otherwise return a copy of the
  51. * string.
  52. */
  53. static char *
  54. decode( char *orig )
  55. {
  56. char *r;
  57. if ( NULL == orig ) {
  58. return NULL;
  59. }
  60. r = slapi_ch_calloc( 1, strlen( orig ) + 2 );
  61. strcpy( r, orig );
  62. if ( heflag ) {
  63. char *s;
  64. for ( s = r; *s != '\0'; ++s ) {
  65. if ( *s == '%' && ldap_utf8isxdigit( s+1 ) && ldap_utf8isxdigit( s+2 )) {
  66. memmove( s, s + 1, 2 );
  67. s[ 2 ] = '\0';
  68. *s = strtoul( s, NULL, 16 );
  69. memmove( s + 1, s + 3, strlen( s + 3 ) + 1 );
  70. }
  71. }
  72. }
  73. return r;
  74. }
  75. static slapdFrontendConfig_t *
  76. init_config(char *configdir)
  77. {
  78. char *abs_configdir = NULL;
  79. char *configfile = NULL;
  80. char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE];
  81. slapdFrontendConfig_t *slapdFrontendConfig = NULL;
  82. if (configdir == NULL) { /* use default */
  83. configdir = TEMPLATEDIR;
  84. configfile = "template-dse.ldif";
  85. }
  86. /* kexcoff: quite the same as slapd_bootstrap_config */
  87. FrontendConfig_init();
  88. abs_configdir = rel2abspath( configdir );
  89. if ( config_set_configdir( "configdir (-D)", abs_configdir,
  90. errorbuf, 1) != LDAP_SUCCESS )
  91. {
  92. fprintf( stderr, "%s\n", errorbuf );
  93. slapi_ch_free_string(&abs_configdir);
  94. return( NULL );
  95. }
  96. slapi_ch_free_string(&abs_configdir);
  97. slapdFrontendConfig = getFrontendConfig();
  98. if (0 == slapd_config(slapdFrontendConfig->configdir, configfile)) {
  99. fprintf(stderr,
  100. "The configuration files in directory %s could not be read or were not found. Please refer to the error log or output for more information.\n",
  101. slapdFrontendConfig->configdir);
  102. return(NULL);
  103. }
  104. return slapdFrontendConfig;
  105. }
  106. int
  107. main( argc, argv )
  108. int argc;
  109. char *argv[];
  110. {
  111. int i, rc;
  112. char *enc, *cmp, *name;
  113. struct pw_scheme *pwsp, *cmppwsp;
  114. extern int optind;
  115. char *cpwd = NULL; /* candidate password for comparison */
  116. slapdFrontendConfig_t *slapdFrontendConfig = NULL;
  117. char *opts = "Hs:c:D:";
  118. name = argv[ 0 ];
  119. pwsp = cmppwsp = NULL;
  120. PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 0 );
  121. /* Initialize NSS to make ds_salted_sha1_pw_enc() work */
  122. if (NSS_NoDB_Init(NULL) != SECSuccess) {
  123. fprintf( stderr, "Fatal error: unable to initialize the NSS subcomponent." );
  124. return( 1 );
  125. }
  126. while (( i = getopt( argc, argv, opts )) != EOF ) {
  127. switch ( i ) {
  128. case 'D':
  129. if (slapdFrontendConfig) {
  130. fprintf(stderr, "The -D configdir argument must be given only once, and must be the first argument given\n");
  131. usage(name);
  132. return 1;
  133. }
  134. if (!(slapdFrontendConfig = init_config(optarg))) {
  135. return(1);
  136. }
  137. break;
  138. case 's': /* set hash scheme */
  139. if (!slapdFrontendConfig) {
  140. if (!(slapdFrontendConfig = init_config(NULL))) {
  141. usage( name );
  142. return(1);
  143. }
  144. }
  145. if (( pwsp = pw_name2scheme( optarg )) == NULL ) {
  146. fprintf( stderr, "%s: unknown hash scheme \"%s\"\n", name,
  147. optarg );
  148. return( 1 );
  149. }
  150. break;
  151. case 'c': /* compare encoded password to password */
  152. if (!slapdFrontendConfig) {
  153. if (!(slapdFrontendConfig = init_config(NULL))) {
  154. usage( name );
  155. return(1);
  156. }
  157. }
  158. cpwd = optarg;
  159. break;
  160. case 'H': /* password(s) is(are) hex-encoded */
  161. if (!slapdFrontendConfig) {
  162. if (!(slapdFrontendConfig = init_config(NULL))) {
  163. usage( name );
  164. return(1);
  165. }
  166. }
  167. heflag = 1;
  168. break;
  169. default:
  170. usage( name );
  171. }
  172. }
  173. if (!slapdFrontendConfig) {
  174. if (!init_config(NULL)) {
  175. usage( name );
  176. return(1);
  177. }
  178. }
  179. if ( cpwd != NULL ) {
  180. cmppwsp = pw_val2scheme( decode( cpwd ), &cmp, 1 );
  181. }
  182. if ( cmppwsp != NULL && pwsp != NULL ) {
  183. fprintf( stderr, "%s: do not use -s with -c\n", name );
  184. usage( name );
  185. }
  186. if ( cmppwsp == NULL && pwsp == NULL ) {
  187. pwsp = pw_name2scheme( SALTED_SHA1_SCHEME_NAME );
  188. }
  189. if ( argc <= optind ) {
  190. usage( name );
  191. }
  192. if ( cmppwsp == NULL && pwsp->pws_enc == NULL ) {
  193. fprintf( stderr,
  194. "The scheme \"%s\" does not support password encoding.\n",
  195. pwsp->pws_name );
  196. return( 1 );
  197. }
  198. srand((int)time(NULL)); /* schemes such as crypt use random salt */
  199. for ( rc = 0; optind < argc && rc == 0; ++optind ) {
  200. if ( cmppwsp == NULL ) { /* encode passwords */
  201. if (( enc = (*pwsp->pws_enc)( decode( argv[ optind ] ))) == NULL ) {
  202. perror( name );
  203. return( 1 );
  204. }
  205. puts( enc );
  206. slapi_ch_free_string( &enc );
  207. } else { /* compare passwords */
  208. if (( rc = (*(cmppwsp->pws_cmp))( decode( argv[ optind ]), cmp )) == 0 ) {
  209. printf( "%s: password ok.\n", name );
  210. } else {
  211. printf( "%s: password does not match.\n", name );
  212. }
  213. }
  214. }
  215. return( rc == 0 ? 0 : 1 );
  216. }
  217. /* -------------------------------------------------------------- */
  218. /*
  219. kexcoff: quite similar to slapd_bootstrap_config() from the server,
  220. but it only loads password storage scheme plugins
  221. */
  222. static int
  223. slapd_config(const char *configdir, const char *givenconfigfile)
  224. {
  225. char configfile[MAXPATHLEN+1];
  226. PRFileInfo64 prfinfo;
  227. int rc = 0; /* Fail */
  228. int done = 0;
  229. PRInt32 nr = 0;
  230. PRFileDesc *prfd = 0;
  231. char returntext[SLAPI_DSE_RETURNTEXT_SIZE] = "";
  232. char *buf = 0;
  233. char *lastp = 0;
  234. char *entrystr = 0;
  235. if (!givenconfigfile) {
  236. givenconfigfile = CONFIG_FILENAME;
  237. }
  238. PR_snprintf(configfile, sizeof(configfile), "%s/%s", configdir, givenconfigfile);
  239. if ( (rc = PR_GetFileInfo64( configfile, &prfinfo )) != PR_SUCCESS )
  240. {
  241. fprintf(stderr,
  242. "The given config file %s could not be accessed, error %d\n",
  243. configfile, rc);
  244. exit( 1 );
  245. }
  246. else if (( prfd = PR_Open( configfile, PR_RDONLY,
  247. SLAPD_DEFAULT_FILE_MODE )) == NULL )
  248. {
  249. fprintf(stderr,
  250. "The given config file %s could not be read\n",
  251. configfile);
  252. exit( 1 );
  253. }
  254. else
  255. {
  256. /* read the entire file into core */
  257. buf = slapi_ch_malloc( prfinfo.size + 1 );
  258. if (( nr = slapi_read_buffer( prfd, buf, prfinfo.size )) < 0 )
  259. {
  260. fprintf(stderr,
  261. "Could only read %d of %ld bytes from config file %s\n",
  262. nr, (long int)prfinfo.size, configfile);
  263. exit( 1 );
  264. }
  265. (void)PR_Close(prfd);
  266. buf[ nr ] = '\0';
  267. if(!done)
  268. {
  269. /* Convert LDIF to entry structures */
  270. Slapi_DN plug_dn;
  271. slapi_sdn_init_dn_byref(&plug_dn, PLUGIN_BASE_DN);
  272. while ((entrystr = dse_read_next_entry(buf, &lastp)) != NULL)
  273. {
  274. /*
  275. * XXXmcs: it would be better to also pass
  276. * SLAPI_STR2ENTRY_REMOVEDUPVALS in the flags, but
  277. * duplicate value checking requires that the syntax
  278. * and schema subsystems be initialized... and they
  279. * are not yet.
  280. */
  281. Slapi_Entry *e = slapi_str2entry(entrystr,
  282. SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF);
  283. if (e == NULL)
  284. {
  285. fprintf(stderr,
  286. "The entry [%s] in the configfile %s was empty or could not be parsed\n",
  287. entrystr, configfile);
  288. continue;
  289. }
  290. /* see if the entry is a child of the plugin base dn */
  291. if (slapi_sdn_isgrandparent(&plug_dn,
  292. slapi_entry_get_sdn_const(e)))
  293. {
  294. if ( entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE, "pwdstoragescheme"))
  295. {
  296. /* add the syntax/matching/pwd storage scheme rule plugin */
  297. if (plugin_setup(e, 0, 0, 1, returntext))
  298. {
  299. fprintf(stderr,
  300. "The plugin entry [%s] in the configfile %s was invalid. %s\n",
  301. slapi_entry_get_dn(e), configfile, returntext);
  302. exit(1); /* yes this sucks, but who knows what else would go on if I did the right thing */
  303. }
  304. else
  305. {
  306. e = 0; /* successful plugin_setup consumes entry */
  307. }
  308. }
  309. }
  310. if (e)
  311. slapi_entry_free(e);
  312. }
  313. /* kexcoff: initialize rootpwstoragescheme and pw_storagescheme
  314. * if not explicilty set in the config file
  315. */
  316. config_set_storagescheme();
  317. slapi_sdn_done(&plug_dn);
  318. rc= 1; /* OK */
  319. }
  320. slapi_ch_free_string(&buf);
  321. }
  322. return rc;
  323. }
  324. /*
  325. kexcoff: direclty copied fron the server code
  326. See if the given entry has an attribute with the given name and the
  327. given value; if value is NULL, just test for the presence of the given
  328. attribute; if value is an empty string (i.e. value[0] == 0),
  329. the first value in the attribute will be copied into the given buffer
  330. and returned
  331. */
  332. static int
  333. entry_has_attr_and_value(Slapi_Entry *e, const char *attrname,
  334. char *value)
  335. {
  336. int retval = 0;
  337. Slapi_Attr *attr = 0;
  338. if (!e || !attrname)
  339. return retval;
  340. /* see if the entry has the specified attribute name */
  341. if (!slapi_entry_attr_find(e, attrname, &attr) && attr)
  342. {
  343. /* if value is not null, see if the attribute has that
  344. value */
  345. if (!value)
  346. {
  347. retval = 1;
  348. }
  349. else
  350. {
  351. Slapi_Value *v = 0;
  352. int index = 0;
  353. for (index = slapi_attr_first_value(attr, &v);
  354. v && (index != -1);
  355. index = slapi_attr_next_value(attr, index, &v))
  356. {
  357. const char *s = slapi_value_get_string(v);
  358. if (!s)
  359. continue;
  360. if (!*value)
  361. {
  362. strcpy(value, s);
  363. retval = 1;
  364. break;
  365. }
  366. else if (!strcasecmp(s, value))
  367. {
  368. retval = 1;
  369. break;
  370. }
  371. }
  372. }
  373. }
  374. return retval;
  375. }