util.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* util.c -- utility functions -- functions available form libslapd */
  42. #ifdef _WIN32
  43. #include <direct.h> /* for getcwd */
  44. #else
  45. #include <sys/socket.h>
  46. #include <sys/param.h>
  47. #include <unistd.h>
  48. #include <pwd.h>
  49. #include <stdint.h>
  50. #endif
  51. #include <fcntl.h>
  52. #include <libgen.h>
  53. #include <pk11func.h>
  54. #include "slap.h"
  55. #include "prtime.h"
  56. #include "prinrval.h"
  57. #include "snmp_collator.h"
  58. #define UTIL_ESCAPE_NONE 0
  59. #define UTIL_ESCAPE_HEX 1
  60. #define UTIL_ESCAPE_BACKSLASH 2
  61. #if defined( _WIN32 )
  62. #define _PSEP "\\"
  63. #define _PSEP2 "\\\\"
  64. #define _CSEP '\\'
  65. #else
  66. #define _PSEP "/"
  67. #define _PSEP2 "//"
  68. #define _CSEP '/'
  69. #endif
  70. /* slapi_filter_sprintf macros */
  71. #define ATTRSIZE 256 /* size allowed for an attr name */
  72. #define FILTER_BUF 128 /* initial buffer size for attr value */
  73. #define BUF_INCR 16 /* the amount to increase the FILTER_BUF once it fills up */
  74. static int special_np(unsigned char c)
  75. {
  76. if (c == '\\') {
  77. return UTIL_ESCAPE_BACKSLASH;
  78. }
  79. if (c < 32 || c > 126 || c == '"') {
  80. return UTIL_ESCAPE_HEX;
  81. }
  82. return UTIL_ESCAPE_NONE;
  83. }
  84. static int special_np_and_punct(unsigned char c)
  85. {
  86. if (c == '\\') {
  87. return UTIL_ESCAPE_BACKSLASH;
  88. }
  89. if (c < 32 || c > 126 || c == '"' || c == '*') {
  90. return UTIL_ESCAPE_HEX;
  91. }
  92. return UTIL_ESCAPE_NONE;
  93. }
  94. #ifndef USE_OPENLDAP
  95. static int special_filter(unsigned char c)
  96. {
  97. /*
  98. * Escape all non-printing chars and double-quotes in addition
  99. * to those required by RFC 2254 so that we can use the string
  100. * in log files.
  101. */
  102. return (c < 32 ||
  103. c > 126 ||
  104. c == '*' ||
  105. c == '(' ||
  106. c == ')' ||
  107. c == '\\' ||
  108. c == '"') ? UTIL_ESCAPE_HEX : UTIL_ESCAPE_NONE;
  109. }
  110. #endif
  111. /*
  112. * Used by filter_stuff_func to help extract an attribute so we know
  113. * how to normalize the value.
  114. */
  115. static int
  116. special_attr_char(unsigned char c)
  117. {
  118. return (c < 32 ||
  119. c > 126 ||
  120. c == '*' ||
  121. c == '|' ||
  122. c == '&' ||
  123. c == '!' ||
  124. c == '(' ||
  125. c == ')' ||
  126. c == '\\' ||
  127. c == '=' ||
  128. c == '"');
  129. }
  130. static const char*
  131. do_escape_string (
  132. const char* str,
  133. int len, /* -1 means str is nul-terminated */
  134. char buf[BUFSIZ],
  135. int (*special)(unsigned char)
  136. )
  137. {
  138. const char* s;
  139. const char* last;
  140. int esc;
  141. if (str == NULL) {
  142. *buf = '\0';
  143. return buf;
  144. }
  145. if (len == -1) len = strlen (str);
  146. if (len == 0) return str;
  147. last = str + len - 1;
  148. for (s = str; s <= last; ++s) {
  149. if ( (esc = (*special)((unsigned char)*s))) {
  150. const char* first = str;
  151. char* bufNext = buf;
  152. int bufSpace = BUFSIZ - 4;
  153. while (1) {
  154. if (bufSpace < (s - first)) s = first + bufSpace - 1;
  155. if (s > first) {
  156. memcpy (bufNext, first, s - first);
  157. bufNext += (s - first);
  158. bufSpace -= (s - first);
  159. }
  160. if (s > last) {
  161. break;
  162. }
  163. do {
  164. if (esc == UTIL_ESCAPE_BACKSLASH) {
  165. /* *s is '\\' */
  166. /* If *(s+1) and *(s+2) are both hex digits,
  167. * the char is already escaped. */
  168. if (isxdigit(*(s+1)) && isxdigit(*(s+2))) {
  169. memcpy(bufNext, s, 3);
  170. bufNext += 3;
  171. bufSpace -= 3;
  172. s += 2;
  173. } else {
  174. *bufNext++ = *s; --bufSpace;
  175. }
  176. } else { /* UTIL_ESCAPE_HEX */
  177. *bufNext++ = '\\'; --bufSpace;
  178. if (bufSpace < 3) {
  179. memcpy(bufNext, "..", 2);
  180. bufNext += 2;
  181. goto bail;
  182. }
  183. PR_snprintf(bufNext, 3, "%02x", *(unsigned char*)s);
  184. bufNext += 2; bufSpace -= 2;
  185. }
  186. } while (++s <= last &&
  187. (esc = (*special)((unsigned char)*s)));
  188. if (s > last) break;
  189. first = s;
  190. while ( (esc = (*special)((unsigned char)*s)) == UTIL_ESCAPE_NONE && s <= last) ++s;
  191. }
  192. bail:
  193. *bufNext = '\0';
  194. return buf;
  195. }
  196. }
  197. return str;
  198. }
  199. /*
  200. * Function: escape_string
  201. * Arguments: str: string
  202. * buf: a char array of BUFSIZ length, in which the escaped string will
  203. * be returned.
  204. * Returns: a pointer to buf, if str==NULL or it needed to be escaped, or
  205. * str itself otherwise.
  206. *
  207. * This function should only be used for generating loggable strings.
  208. */
  209. const char*
  210. escape_string (const char* str, char buf[BUFSIZ])
  211. {
  212. return do_escape_string(str,-1,buf,special_np);
  213. }
  214. const char*
  215. escape_string_with_punctuation(const char* str, char buf[BUFSIZ])
  216. {
  217. return do_escape_string(str,-1,buf,special_np_and_punct);
  218. }
  219. #define ESCAPE_FILTER 1
  220. #define NORM_FILTER 2
  221. struct filter_ctx {
  222. char *buf;
  223. char attr[ATTRSIZE];
  224. int attr_position;
  225. int attr_found;
  226. int buf_size;
  227. int buf_len;
  228. int next_arg_needs_esc_norm;
  229. int skip_escape;
  230. };
  231. /*
  232. * This function is called by slapi_filter_sprintf to escape/normalize certain values
  233. */
  234. static PRIntn
  235. filter_stuff_func(void *arg, const char *val, PRUint32 slen)
  236. {
  237. struct filter_ctx *ctx = (struct filter_ctx *)arg;
  238. #if defined (USE_OPENLDAP)
  239. struct berval escaped_filter;
  240. struct berval raw_filter;
  241. #endif
  242. char *buf = (char *)val;
  243. int extra_space;
  244. int filter_len = slen;
  245. /* look at val - if val is one of our special keywords, and make a note of it for the next pass */
  246. if (strcmp(val, ESC_NEXT_VAL) == 0){
  247. ctx->next_arg_needs_esc_norm |= ESCAPE_FILTER;
  248. return 0;
  249. }
  250. if (strcmp(val, NORM_NEXT_VAL) == 0){
  251. ctx->next_arg_needs_esc_norm |= NORM_FILTER;
  252. return 0;
  253. }
  254. if (strcmp(val, ESC_AND_NORM_NEXT_VAL) == 0){
  255. ctx->next_arg_needs_esc_norm = NORM_FILTER | ESCAPE_FILTER;
  256. return 0;
  257. }
  258. /*
  259. * Start collecting the attribute name so we can use the correct
  260. * syntax normalization func.
  261. */
  262. if(ctx->attr_found == 0 && ctx->attr_position < (ATTRSIZE - 1)){
  263. if(ctx->attr[0] == '\0'){
  264. if(strstr(val,"=")){
  265. /* we have an attr we need to record */
  266. if(!special_attr_char(val[0])){
  267. memcpy(ctx->attr, val, 1);
  268. ctx->attr_position++;
  269. }
  270. } else {
  271. /*
  272. * We have passed in an attribute as a arg - so we can just set the
  273. * attr with val. The next pass should be '=', otherwise we will
  274. * reset it.
  275. */
  276. memcpy(ctx->attr, val, slen);
  277. ctx->attr_position = slen;
  278. }
  279. } else {
  280. if(val[0] == '='){ /* hit the end of the attribute name */
  281. ctx->attr_found = 1;
  282. } else {
  283. if(special_attr_char(val[0])){
  284. /* this is not an attribute, we should not be collecting this, reset everything */
  285. memset(ctx->attr, '\0', ATTRSIZE);
  286. ctx->attr_position = 0;
  287. } else {
  288. memcpy(ctx->attr + ctx->attr_position, val, 1);
  289. ctx->attr_position++;
  290. }
  291. }
  292. }
  293. }
  294. if (ctx->next_arg_needs_esc_norm && !ctx->skip_escape){
  295. /*
  296. * Normalize the filter value first
  297. */
  298. if(ctx->next_arg_needs_esc_norm & NORM_FILTER){
  299. char *norm_val = NULL;
  300. if(ctx->attr_found){
  301. slapi_attr_value_normalize(NULL, NULL, ctx->attr , buf, 1, &norm_val );
  302. if(norm_val){
  303. buf = norm_val;
  304. filter_len = strlen(buf);
  305. }
  306. }
  307. }
  308. /*
  309. * Escape the filter value
  310. */
  311. if(ctx->next_arg_needs_esc_norm & ESCAPE_FILTER){
  312. #if defined (USE_OPENLDAP)
  313. raw_filter.bv_val = (char *)buf;
  314. raw_filter.bv_len = filter_len;
  315. if(ldap_bv2escaped_filter_value(&raw_filter, &escaped_filter) != 0){
  316. LDAPDebug(LDAP_DEBUG_TRACE, "slapi_filter_sprintf: failed to escape filter value(%s)\n",val,0,0);
  317. ctx->next_arg_needs_esc_norm = 0;
  318. return -1;
  319. } else {
  320. filter_len = escaped_filter.bv_len;
  321. buf = escaped_filter.bv_val;
  322. }
  323. #else
  324. char *val2 = NULL;
  325. buf = slapi_ch_calloc(sizeof(char), filter_len*3 + 1);
  326. val2 = (char *)do_escape_string(val, filter_len, buf, special_filter);
  327. if(val2 == NULL){
  328. LDAPDebug(LDAP_DEBUG_TRACE, "slapi_filter_sprintf: failed to escape filter value(%s)\n",val,0,0);
  329. ctx->next_arg_needs_esc_norm = 0;
  330. slapi_ch_free_string(&buf);
  331. return -1;
  332. } else if (val == val2) { /* value did not need escaping and was just returned */
  333. strcpy(buf, val); /* just use value as-is - len did not change */
  334. } else {
  335. filter_len = strlen(buf);
  336. }
  337. #endif
  338. }
  339. /*
  340. * Now add the new value to the buffer, and allocate more memory if needed
  341. */
  342. if (ctx->buf_size + filter_len >= ctx->buf_len){
  343. /* increase buffer for this filter */
  344. extra_space = (ctx->buf_len + filter_len + BUF_INCR);
  345. ctx->buf = slapi_ch_realloc(ctx->buf, sizeof(char) * extra_space);
  346. ctx->buf_len = extra_space;
  347. }
  348. /* append the escaped value */
  349. memcpy(ctx->buf + ctx->buf_size, buf, filter_len);
  350. ctx->buf_size += filter_len;
  351. /* done with the value, reset everything */
  352. ctx->next_arg_needs_esc_norm = 0;
  353. ctx->attr_found = 0;
  354. ctx->attr_position = 0;
  355. memset(ctx->attr, '\0', ATTRSIZE);
  356. slapi_ch_free_string(&buf);
  357. return filter_len;
  358. } else { /* process arg as is */
  359. /* check if we have enough room in our buffer */
  360. if (ctx->buf_size + slen >= ctx->buf_len){
  361. /* increase buffer for this filter */
  362. extra_space = (ctx->buf_len + slen + BUF_INCR);
  363. ctx->buf = slapi_ch_realloc((char *)ctx->buf, sizeof(char) * extra_space);
  364. ctx->buf_len = extra_space;
  365. }
  366. memcpy(ctx->buf + ctx->buf_size, buf, slen);
  367. ctx->buf_size += slen;
  368. return slen;
  369. }
  370. }
  371. /*
  372. * This is basically like slapi_ch_smprintf() except it can handle special
  373. * keywords that will cause the next value to be escaped and/or normalized.
  374. *
  375. * ESC_NEXT_VAL - escape the next value
  376. * NORM_NEXT_VAL - normalize the next value
  377. * ESC_AND_NORM_NEXT_VAL - escape and normalize the next value
  378. *
  379. * Example:
  380. *
  381. * slapi_filter_sprintf("cn=%s%s", ESC_NEXT_VAL, value);
  382. * slapi_filter_sprintf("(|(cn=%s%s)(sn=%s%s))", ESC_NEXT_VAL, value, NORM_NEXT_VAL, value);
  383. *
  384. * Note: you need a string format specifier(%s) for each keyword
  385. */
  386. char*
  387. slapi_filter_sprintf(const char *fmt, ...)
  388. {
  389. struct filter_ctx ctx;
  390. va_list args;
  391. char *buf;
  392. int rc;
  393. buf = slapi_ch_calloc(sizeof(char), FILTER_BUF + 1);
  394. ctx.buf = buf;
  395. memset(ctx.attr,'\0', ATTRSIZE);
  396. ctx.attr_position = 0;
  397. ctx.attr_found = 0;
  398. ctx.buf_len = FILTER_BUF;
  399. ctx.buf_size = 0;
  400. ctx.next_arg_needs_esc_norm = 0;
  401. ctx.skip_escape = 0;
  402. va_start(args, fmt);
  403. rc = PR_vsxprintf(filter_stuff_func, &ctx, fmt, args);
  404. if(rc == -1){
  405. /* transformation failed, just return non-normalized/escaped string */
  406. ctx.skip_escape = 1;
  407. PR_vsxprintf(filter_stuff_func, &ctx, fmt, args);
  408. }
  409. va_end(args);
  410. return ctx.buf;
  411. }
  412. /*
  413. * escape special characters in values used in search filters
  414. *
  415. * caller must free the returned value
  416. */
  417. char*
  418. slapi_escape_filter_value(char* filter_str, int len)
  419. {
  420. #if defined (USE_OPENLDAP)
  421. struct berval escaped_filter;
  422. struct berval raw_filter;
  423. #endif
  424. int filter_len;
  425. /*
  426. * Check the length for special cases
  427. */
  428. if(len == -1){
  429. /* filter str is null terminated */
  430. filter_len = strlen(filter_str);
  431. } else if (len == 0){
  432. /* return the filter as is */
  433. return slapi_ch_strdup(filter_str);
  434. } else {
  435. /* the len is the length */
  436. filter_len = len;
  437. }
  438. #if defined (USE_OPENLDAP)
  439. /*
  440. * Construct the berval and escape it
  441. */
  442. raw_filter.bv_val = filter_str;
  443. raw_filter.bv_len = filter_len;
  444. if(ldap_bv2escaped_filter_value(&raw_filter, &escaped_filter) != 0){
  445. LDAPDebug(LDAP_DEBUG_TRACE, "slapi_escape_filter_value: failed to escape filter value(%s)\n",filter_str,0,0);
  446. return NULL;
  447. } else {
  448. return escaped_filter.bv_val;
  449. }
  450. #else
  451. char *buf = slapi_ch_calloc(sizeof(char), filter_len*3+1);
  452. char *esc_str = (char *)do_escape_string(filter_str, filter_len, buf, special_filter);
  453. if(esc_str != buf){
  454. slapi_ch_free_string(&buf);
  455. return slapi_ch_strdup(esc_str);
  456. } else {
  457. return buf;
  458. }
  459. #endif
  460. }
  461. /*
  462. ** This function takes a quoted attribute value of the form "abc",
  463. ** and strips off the enclosing quotes. It also deals with quoted
  464. ** characters by removing the preceeding '\' character.
  465. **
  466. */
  467. void
  468. strcpy_unescape_value( char *d, const char *s )
  469. {
  470. int gotesc = 0;
  471. const char *end = s + strlen(s);
  472. for ( ; *s; s++ )
  473. {
  474. switch ( *s )
  475. {
  476. case '"':
  477. break;
  478. case '\\':
  479. gotesc = 1;
  480. if ( s+2 < end ) {
  481. int n = slapi_hexchar2int( s[1] );
  482. if ( n >= 0 && n < 16 ) {
  483. int n2 = slapi_hexchar2int( s[2] );
  484. if ( n2 >= 0 ) {
  485. n = (n << 4) + n2;
  486. if (n == 0) { /* don't change \00 */
  487. *d++ = *s++;
  488. *d++ = *s++;
  489. *d++ = *s;
  490. } else { /* change \xx to a single char */
  491. *d++ = (char)n;
  492. s += 2;
  493. }
  494. gotesc = 0;
  495. }
  496. }
  497. }
  498. /* This is an escaped single character (like \"), so
  499. * just copy the special character and not the escape.
  500. * We need to be careful to not go past the end of
  501. * the string when the loop increments s. */
  502. if (gotesc && (s+1 < end)) {
  503. s++;
  504. *d++ = *s;
  505. gotesc = 0;
  506. }
  507. break;
  508. default:
  509. *d++ = *s;
  510. break;
  511. }
  512. }
  513. *d = '\0';
  514. }
  515. /* functions to convert between an entry and a set of mods */
  516. int slapi_mods2entry (Slapi_Entry **e, const char *idn, LDAPMod **iattrs)
  517. {
  518. int i, rc = LDAP_SUCCESS;
  519. LDAPMod **attrs= NULL;
  520. PR_ASSERT (idn);
  521. PR_ASSERT (iattrs);
  522. PR_ASSERT (e);
  523. attrs = normalize_mods2bvals((const LDAPMod **)iattrs);
  524. PR_ASSERT (attrs);
  525. /* Construct an entry */
  526. *e = slapi_entry_alloc();
  527. PR_ASSERT (*e);
  528. slapi_entry_init(*e, slapi_ch_strdup(idn), NULL);
  529. for (i = 0; rc==LDAP_SUCCESS && attrs[ i ]!=NULL; i++)
  530. {
  531. char *normtype;
  532. Slapi_Value **vals;
  533. /*
  534. * slapi_entry_apply_mod_extension applys mod and stores
  535. * the result in the extension
  536. * return value: 1 - mod is applied and stored in extension
  537. * -1 - mod is applied and failed
  538. * 0 - mod is nothing to do with extension
  539. */
  540. rc = slapi_entry_apply_mod_extension(*e, attrs[i], -1);
  541. if (rc) {
  542. if (1 == rc) {
  543. rc = LDAP_SUCCESS;
  544. } else {
  545. rc = LDAP_OPERATIONS_ERROR;
  546. }
  547. #if !defined(USE_OLD_UNHASHED)
  548. /* In case USE_OLD_UNHASHED,
  549. * unhashed pw needs to be in attr, too. */
  550. continue;
  551. #endif
  552. }
  553. normtype = slapi_attr_syntax_normalize(attrs[ i ]->mod_type);
  554. valuearray_init_bervalarray(attrs[ i ]->mod_bvalues, &vals);
  555. if (strcasecmp(normtype, SLAPI_USERPWD_ATTR) == 0)
  556. {
  557. pw_encodevals(vals);
  558. }
  559. /* set entry uniqueid - also adds attribute to the list */
  560. if (strcasecmp(normtype, SLAPI_ATTR_UNIQUEID) == 0) {
  561. if (vals) {
  562. slapi_entry_set_uniqueid (*e,
  563. slapi_ch_strdup (slapi_value_get_string(vals[0])));
  564. } else {
  565. rc = LDAP_NO_SUCH_ATTRIBUTE;
  566. }
  567. } else {
  568. rc = slapi_entry_add_values_sv(*e, normtype, vals);
  569. }
  570. valuearray_free(&vals);
  571. if (rc != LDAP_SUCCESS)
  572. {
  573. LDAPDebug2Args(LDAP_DEBUG_ANY,
  574. "slapi_mods2entry: add_values for type %s failed (rc: %d)\n",
  575. normtype, rc );
  576. slapi_entry_free (*e);
  577. *e = NULL;
  578. }
  579. slapi_ch_free((void **) &normtype);
  580. }
  581. freepmods(attrs);
  582. return rc;
  583. }
  584. int
  585. slapi_entry2mods (const Slapi_Entry *e, char **dn, LDAPMod ***attrs)
  586. {
  587. Slapi_Mods smods;
  588. Slapi_Attr *attr;
  589. Slapi_Value **va;
  590. char *type;
  591. int rc;
  592. PR_ASSERT (e && attrs);
  593. if (dn)
  594. *dn = slapi_ch_strdup (slapi_entry_get_dn ((Slapi_Entry *)e));
  595. slapi_mods_init (&smods, 0);
  596. rc = slapi_entry_first_attr(e, &attr);
  597. while (rc == 0)
  598. {
  599. if ( NULL != ( va = attr_get_present_values( attr ))) {
  600. slapi_attr_get_type(attr, &type);
  601. slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, type, va );
  602. }
  603. rc = slapi_entry_next_attr(e, attr, &attr);
  604. }
  605. #if !defined(USE_OLD_UNHASHED)
  606. if (SLAPD_UNHASHED_PW_ON == config_get_unhashed_pw_switch()) {
  607. /* store unhashed passwd is enabled */
  608. /* In case USE_OLD_UNHASHED, unhashed pw is already in mods */
  609. /* add extension to mods */
  610. rc = slapi_pw_get_entry_ext((Slapi_Entry *)e, &va);
  611. if (LDAP_SUCCESS == rc) {
  612. /* va is copied and set to smods */
  613. slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD,
  614. PSEUDO_ATTR_UNHASHEDUSERPASSWORD, va);
  615. }
  616. }
  617. #endif
  618. *attrs = slapi_mods_get_ldapmods_passout (&smods);
  619. slapi_mods_done (&smods);
  620. return 0;
  621. }
  622. /******************************************************************************
  623. *
  624. * normalize_mods2bvals
  625. *
  626. * Return value: normalized mods
  627. * The values/bvals are all duplicated in this function since
  628. * the normalized mods are freed with ldap_mods_free by the caller.
  629. *
  630. *******************************************************************************/
  631. LDAPMod **
  632. normalize_mods2bvals(const LDAPMod **mods)
  633. {
  634. int w, x, vlen, num_values, num_mods;
  635. LDAPMod **normalized_mods;
  636. if (mods == NULL)
  637. {
  638. return NULL;
  639. }
  640. /* first normalize the mods so they are bvalues */
  641. /* count the number of mods -- sucks but should be small */
  642. num_mods = 1;
  643. for (w=0; mods[w] != NULL; w++) num_mods++;
  644. normalized_mods = (LDAPMod **) slapi_ch_calloc(num_mods, sizeof(LDAPMod *));
  645. for (w = 0; mods[w] != NULL; w++)
  646. {
  647. Slapi_Attr a = {0};
  648. slapi_attr_init(&a, mods[w]->mod_type);
  649. int is_dn_syntax = 0;
  650. struct berval **normmbvp = NULL;
  651. /* Check if the type of the to-be-added values has DN syntax
  652. * or not. */
  653. if (slapi_attr_is_dn_syntax_attr(&a)) {
  654. is_dn_syntax = 1;
  655. }
  656. attr_done(&a);
  657. /* copy each mod into a normalized modbvalue */
  658. normalized_mods[w] = (LDAPMod *) slapi_ch_calloc(1, sizeof(LDAPMod));
  659. normalized_mods[w]->mod_op = mods[w]->mod_op | LDAP_MOD_BVALUES;
  660. normalized_mods[w]->mod_type = slapi_ch_strdup(mods[w]->mod_type);
  661. /*
  662. * count the number of values -- kinda sucks but probably
  663. * less expensive then reallocing, and num_values
  664. * should typically be very small
  665. */
  666. num_values = 0;
  667. if (mods[w]->mod_op & LDAP_MOD_BVALUES)
  668. {
  669. for (x = 0; mods[w]->mod_bvalues != NULL &&
  670. mods[w]->mod_bvalues[x] != NULL; x++)
  671. {
  672. num_values++;
  673. }
  674. } else {
  675. for (x = 0; mods[w]->mod_values != NULL &&
  676. mods[w]->mod_values[x] != NULL; x++)
  677. {
  678. num_values++;
  679. }
  680. }
  681. if (num_values > 0)
  682. {
  683. normalized_mods[w]->mod_bvalues = (struct berval **)
  684. slapi_ch_calloc(num_values + 1, sizeof(struct berval *));
  685. } else {
  686. normalized_mods[w]->mod_bvalues = NULL;
  687. }
  688. if (mods[w]->mod_op & LDAP_MOD_BVALUES)
  689. {
  690. struct berval **mbvp = NULL;
  691. for (mbvp = mods[w]->mod_bvalues,
  692. normmbvp = normalized_mods[w]->mod_bvalues;
  693. mbvp && *mbvp; mbvp++, normmbvp++)
  694. {
  695. if (is_dn_syntax) {
  696. Slapi_DN *sdn = slapi_sdn_new_dn_byref((*mbvp)->bv_val);
  697. if (slapi_sdn_get_dn(sdn)) {
  698. *normmbvp =
  699. (struct berval *)slapi_ch_malloc(sizeof(struct berval));
  700. (*normmbvp)->bv_val =
  701. slapi_ch_strdup(slapi_sdn_get_dn(sdn));
  702. (*normmbvp)->bv_len = slapi_sdn_get_ndn_len(sdn);
  703. } else {
  704. /* normalization failed; use the original */
  705. *normmbvp = ber_bvdup(*mbvp);
  706. }
  707. slapi_sdn_free(&sdn);
  708. } else {
  709. *normmbvp = ber_bvdup(*mbvp);
  710. }
  711. }
  712. } else {
  713. char **mvp = NULL;
  714. for (mvp = mods[w]->mod_values,
  715. normmbvp = normalized_mods[w]->mod_bvalues;
  716. mvp && *mvp; mvp++, normmbvp++)
  717. {
  718. vlen = strlen(*mvp);
  719. *normmbvp =
  720. (struct berval *)slapi_ch_malloc(sizeof(struct berval));
  721. if (is_dn_syntax) {
  722. Slapi_DN *sdn = slapi_sdn_new_dn_byref(*mvp);
  723. if (slapi_sdn_get_dn(sdn)) {
  724. (*normmbvp)->bv_val =
  725. slapi_ch_strdup(slapi_sdn_get_dn(sdn));
  726. (*normmbvp)->bv_len = slapi_sdn_get_ndn_len(sdn);
  727. } else {
  728. /* normalization failed; use the original */
  729. (*normmbvp)->bv_val = slapi_ch_malloc(vlen + 1);
  730. memcpy((*normmbvp)->bv_val, *mvp, vlen);
  731. (*normmbvp)->bv_val[vlen] = '\0';
  732. (*normmbvp)->bv_len = vlen;
  733. }
  734. slapi_sdn_free(&sdn);
  735. } else {
  736. (*normmbvp)->bv_val = slapi_ch_malloc(vlen + 1);
  737. memcpy((*normmbvp)->bv_val, *mvp, vlen);
  738. (*normmbvp)->bv_val[vlen] = '\0';
  739. (*normmbvp)->bv_len = vlen;
  740. }
  741. }
  742. }
  743. PR_ASSERT(normmbvp - normalized_mods[w]->mod_bvalues <= num_values);
  744. /* don't forget to null terminate it */
  745. if (num_values > 0)
  746. {
  747. *normmbvp = NULL;
  748. }
  749. }
  750. /* don't forget to null terminate the normalize list of mods */
  751. normalized_mods[w] = NULL;
  752. return(normalized_mods);
  753. }
  754. /*
  755. * Return true if the given path is an absolute path, false otherwise
  756. */
  757. int
  758. is_abspath(const char *path)
  759. {
  760. if (path == NULL || *path == '\0') {
  761. return 0; /* empty path is not absolute? */
  762. }
  763. #if defined( XP_WIN32 )
  764. if (path[0] == '/' || path[0] == '\\' ||
  765. (isalpha(path[0]) && (path[1] == ':'))) {
  766. return 1; /* Windows abs path */
  767. }
  768. #else
  769. if (path[0] == '/') {
  770. return 1; /* unix abs path */
  771. }
  772. #endif
  773. return 0; /* not an abs path */
  774. }
  775. static void
  776. clean_path(char **norm_path)
  777. {
  778. char **np;
  779. for (np = norm_path; np && *np; np++)
  780. slapi_ch_free_string(np);
  781. slapi_ch_free((void **)&norm_path);
  782. }
  783. static char **
  784. normalize_path(char *path)
  785. {
  786. char *dname = NULL;
  787. char *dnamep = NULL;
  788. char **dirs = NULL;
  789. char **rdirs = NULL;
  790. char **dp = NULL;
  791. char **rdp;
  792. int elimdots = 0;
  793. if (NULL == path || '\0' == *path) {
  794. return NULL;
  795. }
  796. dirs = (char **)slapi_ch_calloc(strlen(path), sizeof(char *));
  797. rdirs = (char **)slapi_ch_calloc(strlen(path), sizeof(char *));
  798. dp = dirs;
  799. dname = slapi_ch_strdup(path);
  800. do {
  801. dnamep = strrchr(dname, _CSEP);
  802. if (NULL == dnamep) {
  803. dnamep = dname;
  804. } else {
  805. *dnamep = '\0';
  806. dnamep++;
  807. }
  808. if (0 != strcmp(dnamep, ".") && strlen(dnamep) > 0) {
  809. *dp++ = slapi_ch_strdup(dnamep); /* rm "/./" and "//" in the path */
  810. }
  811. } while ( dnamep > dname /* == -> no more _CSEP */ );
  812. slapi_ch_free_string(&dname);
  813. /* remove "xxx/.." in the path */
  814. for (dp = dirs, rdp = rdirs; dp && *dp; dp++) {
  815. while (*dp && 0 == strcmp(*dp, "..")) {
  816. dp++;
  817. elimdots++;
  818. }
  819. if (elimdots > 0) {
  820. elimdots--;
  821. } else if (*dp) {
  822. *rdp++ = slapi_ch_strdup(*dp);
  823. }
  824. }
  825. /* reverse */
  826. for (--rdp, dp = rdirs; rdp >= dp && rdp >= rdirs; --rdp, dp++) {
  827. char *tmpp = *dp;
  828. *dp = *rdp;
  829. *rdp = tmpp;
  830. }
  831. clean_path(dirs);
  832. return rdirs;
  833. }
  834. /*
  835. * Take "relpath" and prepend the current working directory to it
  836. * if it isn't an absolute pathname already. The caller is responsible
  837. * for freeing the returned string.
  838. */
  839. char *
  840. rel2abspath( char *relpath )
  841. {
  842. return rel2abspath_ext( relpath, NULL );
  843. }
  844. char *
  845. rel2abspath_ext( char *relpath, char *cwd )
  846. {
  847. char abspath[ MAXPATHLEN + 1 ];
  848. char *retpath = NULL;
  849. #if defined( _WIN32 )
  850. CHAR szDrive[_MAX_DRIVE];
  851. CHAR szDir[_MAX_DIR];
  852. CHAR szFname[_MAX_FNAME];
  853. CHAR szExt[_MAX_EXT];
  854. #endif
  855. if ( relpath == NULL ) {
  856. return NULL;
  857. }
  858. #if defined( _WIN32 )
  859. memset (&szDrive, 0, sizeof (szDrive));
  860. memset (&szDir, 0, sizeof (szDir));
  861. memset (&szFname, 0, sizeof (szFname));
  862. memset (&szExt, 0, sizeof (szExt));
  863. _splitpath( relpath, szDrive, szDir, szFname, szExt );
  864. if( szDrive[0] && szDir[0] )
  865. return( slapi_ch_strdup( relpath ));
  866. #endif
  867. if ( relpath[ 0 ] == _CSEP ) { /* absolute path */
  868. PR_snprintf(abspath, sizeof(abspath), "%s", relpath);
  869. } else { /* relative path */
  870. if ( NULL == cwd ) {
  871. if ( getcwd( abspath, MAXPATHLEN ) == NULL ) {
  872. perror( "getcwd" );
  873. LDAPDebug( LDAP_DEBUG_ANY, "Cannot determine current directory\n",
  874. 0, 0, 0 );
  875. exit( 1 );
  876. }
  877. } else {
  878. PR_snprintf(abspath, sizeof(abspath), "%s", cwd);
  879. }
  880. if ( strlen( relpath ) + strlen( abspath ) + 1 > MAXPATHLEN ) {
  881. LDAPDebug( LDAP_DEBUG_ANY, "Pathname \"%s" _PSEP "%s\" too long\n",
  882. abspath, relpath, 0 );
  883. exit( 1 );
  884. }
  885. if ( strcmp( relpath, "." )) {
  886. if ( abspath[ 0 ] != '\0' &&
  887. abspath[ strlen( abspath ) - 1 ] != _CSEP )
  888. {
  889. PL_strcatn( abspath, sizeof(abspath), _PSEP );
  890. }
  891. PL_strcatn( abspath, sizeof(abspath), relpath );
  892. }
  893. }
  894. retpath = slapi_ch_strdup(abspath);
  895. /* if there's no '.' or separators, no need to call normalize_path */
  896. if (NULL != strchr(abspath, '.') || NULL != strstr(abspath, _PSEP))
  897. {
  898. char **norm_path = normalize_path(abspath);
  899. char **np, *rp;
  900. int pathlen = strlen(abspath) + 1;
  901. int usedlen = 0;
  902. for (np = norm_path, rp = retpath; np && *np; np++) {
  903. int thislen = strlen(*np) + 1;
  904. if (0 != strcmp(*np, _PSEP))
  905. PR_snprintf(rp, pathlen - usedlen, "%c%s", _CSEP, *np);
  906. rp += thislen;
  907. usedlen += thislen;
  908. }
  909. clean_path(norm_path);
  910. }
  911. return retpath;
  912. }
  913. /*
  914. * Allocate a buffer large enough to hold a berval's
  915. * value and a terminating null byte. The returned buffer
  916. * is null-terminated. Returns NULL if bval is NULL or if
  917. * bval->bv_val is NULL.
  918. */
  919. char *
  920. slapi_berval_get_string_copy(const struct berval *bval)
  921. {
  922. char *return_value = NULL;
  923. if (NULL != bval && NULL != bval->bv_val)
  924. {
  925. return_value = slapi_ch_malloc(bval->bv_len + 1);
  926. memcpy(return_value, bval->bv_val, bval->bv_len);
  927. return_value[bval->bv_len] = '\0';
  928. }
  929. return return_value;
  930. }
  931. /* Takes a return code supposed to be errno or from a plugin
  932. which we don't expect to see and prints a handy log message */
  933. void slapd_nasty(char* str, int c, int err)
  934. {
  935. char *msg = NULL;
  936. char buffer[100];
  937. PR_snprintf(buffer,sizeof(buffer), "%s BAD %d",str,c);
  938. LDAPDebug(LDAP_DEBUG_ANY,"%s, err=%d %s\n",buffer,err,(msg = strerror( err )) ? msg : "");
  939. }
  940. /* ***************************************************
  941. Random function (very similar to rand_r())
  942. *************************************************** */
  943. int
  944. slapi_rand_r(unsigned int *randx)
  945. {
  946. if (*randx)
  947. {
  948. PK11_RandomUpdate(randx, sizeof(*randx));
  949. }
  950. PK11_GenerateRandom((unsigned char *)randx, (int)sizeof(*randx));
  951. return (int)(*randx & 0x7FFFFFFF);
  952. }
  953. /* ***************************************************
  954. Random function (very similar to rand_r() but takes and returns an array)
  955. Note: there is an identical function in plugins/pwdstorage/ssha_pwd.c.
  956. That module can't use a libslapd function because the module is included
  957. in libds_admin, which doesn't link to libslapd. Eventually, shared
  958. functions should be moved to a shared library.
  959. *************************************************** */
  960. void
  961. slapi_rand_array(void *randx, size_t len)
  962. {
  963. PK11_RandomUpdate(randx, len);
  964. PK11_GenerateRandom((unsigned char *)randx, (int)len);
  965. }
  966. /* ***************************************************
  967. Random function (very similar to rand()...)
  968. *************************************************** */
  969. int
  970. slapi_rand()
  971. {
  972. unsigned int randx = 0;
  973. return slapi_rand_r(&randx);
  974. }
  975. /************************************************************************
  976. Function: DS_Sleep(PRIntervalTime ticks)
  977. Purpose: To replace PR_Sleep()
  978. Author: Scott Hopson <[email protected]>
  979. Description:
  980. Causes the current thread to wait for ticks number of intervals.
  981. In UNIX this is accomplished by using select()
  982. which should be supported across all UNIX platforms.
  983. In WIN32 we simply use the Sleep() function which yields
  984. for the number of milliseconds specified.
  985. ************************************************************************/
  986. #if defined(_WIN32)
  987. #include "windows.h"
  988. void DS_Sleep(PRIntervalTime ticks)
  989. {
  990. DWORD mSecs = PR_IntervalToMilliseconds(ticks);
  991. Sleep(mSecs);
  992. }
  993. #else /*** UNIX ***/
  994. #include <sys/time.h>
  995. void DS_Sleep(PRIntervalTime ticks)
  996. {
  997. long mSecs = PR_IntervalToMilliseconds(ticks);
  998. struct timeval tm;
  999. tm.tv_sec = mSecs / 1000;
  1000. tm.tv_usec = (mSecs % 1000) * 1000;
  1001. select(0,NULL,NULL,NULL,&tm);
  1002. }
  1003. #endif
  1004. /*****************************************************************************
  1005. * strarray2str(): convert the array of strings in "a" into a single
  1006. * space-separated string like:
  1007. * str1 str2 str3
  1008. * If buf is too small, the result will be truncated and end with "...".
  1009. * If include_quotes is non-zero, double quote marks are included around
  1010. * the string, e.g.,
  1011. * "str2 str2 str3"
  1012. *
  1013. * Returns: 0 if completely successful and -1 if result is truncated.
  1014. */
  1015. int
  1016. strarray2str( char **a, char *buf, size_t buflen, int include_quotes )
  1017. {
  1018. int rc = 0; /* optimistic */
  1019. char *p = buf;
  1020. size_t totlen = 0;
  1021. if ( include_quotes ) {
  1022. if ( buflen < 3 ) {
  1023. return -1; /* not enough room for the quote marks! */
  1024. }
  1025. *p++ = '"';
  1026. ++totlen;
  1027. }
  1028. if ( NULL != a ) {
  1029. int ii;
  1030. size_t len = 0;
  1031. for ( ii = 0; a[ ii ] != NULL; ii++ ) {
  1032. if ( ii > 0 ) {
  1033. *p++ = ' ';
  1034. totlen++;
  1035. }
  1036. len = strlen( a[ ii ]);
  1037. if ( totlen + len > buflen - 5 ) {
  1038. strcpy ( p, "..." );
  1039. p += 3;
  1040. totlen += 3;
  1041. rc = -1;
  1042. break; /* result truncated */
  1043. } else {
  1044. strcpy( p, a[ ii ]);
  1045. p += len;
  1046. totlen += len;
  1047. }
  1048. }
  1049. }
  1050. if ( include_quotes ) {
  1051. *p++ = '"';
  1052. ++totlen;
  1053. }
  1054. buf[ totlen ] = '\0';
  1055. return( rc );
  1056. }
  1057. /*****************************************************************************/
  1058. /* Changes the ownership of the given file/directory if not
  1059. already the owner
  1060. Returns 0 upon success or non-zero otherwise, usually -1 if
  1061. some system error occurred
  1062. */
  1063. #ifndef _WIN32
  1064. int
  1065. slapd_chown_if_not_owner(const char *filename, uid_t uid, gid_t gid)
  1066. {
  1067. int fd = -1;
  1068. struct stat statbuf;
  1069. int result = 1;
  1070. if (!filename)
  1071. return result;
  1072. fd = open(filename, O_RDONLY);
  1073. if (fd == -1) {
  1074. return result;
  1075. }
  1076. memset(&statbuf, '\0', sizeof(statbuf));
  1077. if (!(result = fstat(fd, &statbuf)))
  1078. {
  1079. if (((uid != -1) && (uid != statbuf.st_uid)) ||
  1080. ((gid != -1) && (gid != statbuf.st_gid)))
  1081. {
  1082. result = fchown(fd, uid, gid);
  1083. }
  1084. }
  1085. close(fd);
  1086. return result;
  1087. }
  1088. #endif
  1089. /*
  1090. * Compare 2 pathes
  1091. * Paths could contain ".", "..", "//" in the path, thus normalize them first.
  1092. * One or two of the paths could be a relative path.
  1093. */
  1094. int
  1095. slapd_comp_path(char *p0, char *p1)
  1096. {
  1097. int rval = 0;
  1098. char *norm_p0 = rel2abspath(p0);
  1099. char *norm_p1 = rel2abspath(p1);
  1100. rval = strcmp(norm_p0, norm_p1);
  1101. slapi_ch_free_string(&norm_p0);
  1102. slapi_ch_free_string(&norm_p1);
  1103. return rval;
  1104. }
  1105. /*
  1106. Takes an unsigned char value and converts it to a hex string.
  1107. The string s is written, and the caller must ensure s has enough
  1108. space. For hex numbers, the upper argument says to use a-f or A-F.
  1109. The return value is the address of the next char after the last one written.
  1110. */
  1111. char *
  1112. slapi_u8_to_hex(uint8_t val, char *s, uint8_t upper) {
  1113. static char ldigits[] = "0123456789abcdef";
  1114. static char udigits[] = "0123456789ABCDEF";
  1115. char *digits;
  1116. if (upper) {
  1117. digits = udigits;
  1118. } else {
  1119. digits = ldigits;
  1120. }
  1121. s[0] = digits[val >> 4];
  1122. s[1] = digits[val & 0xf];
  1123. return &s[2];
  1124. }
  1125. char *
  1126. slapi_u16_to_hex(uint16_t val, char *s, uint8_t upper) {
  1127. static char ldigits[] = "0123456789abcdef";
  1128. static char udigits[] = "0123456789ABCDEF";
  1129. char *digits;
  1130. if (upper) {
  1131. digits = udigits;
  1132. } else {
  1133. digits = ldigits;
  1134. }
  1135. s[0] = digits[val >> 12];
  1136. s[1] = digits[(val >> 8) & 0xf];
  1137. s[2] = digits[(val >> 4) & 0xf];
  1138. s[3] = digits[val & 0xf];
  1139. return &s[4];
  1140. }
  1141. char *
  1142. slapi_u32_to_hex(uint32_t val, char *s, uint8_t upper) {
  1143. static char ldigits[] = "0123456789abcdef";
  1144. static char udigits[] = "0123456789ABCDEF";
  1145. char *digits;
  1146. if (upper) {
  1147. digits = udigits;
  1148. } else {
  1149. digits = ldigits;
  1150. }
  1151. s[0] = digits[val >> 28];
  1152. s[1] = digits[(val >> 24) & 0xf];
  1153. s[2] = digits[(val >> 20) & 0xf];
  1154. s[3] = digits[(val >> 16) & 0xf];
  1155. s[4] = digits[(val >> 12) & 0xf];
  1156. s[5] = digits[(val >> 8) & 0xf];
  1157. s[6] = digits[(val >> 4) & 0xf];
  1158. s[7] = digits[val & 0xf];
  1159. return &s[8];
  1160. }
  1161. char *
  1162. slapi_u64_to_hex(uint64_t val, char *s, uint8_t upper) {
  1163. static char ldigits[] = "0123456789abcdef";
  1164. static char udigits[] = "0123456789ABCDEF";
  1165. char *digits;
  1166. if (upper) {
  1167. digits = udigits;
  1168. } else {
  1169. digits = ldigits;
  1170. }
  1171. s[0] = digits[val >> 60];
  1172. s[1] = digits[(val >> 56) & 0xf];
  1173. s[2] = digits[(val >> 52) & 0xf];
  1174. s[3] = digits[(val >> 48) & 0xf];
  1175. s[4] = digits[(val >> 44) & 0xf];
  1176. s[5] = digits[(val >> 40) & 0xf];
  1177. s[6] = digits[(val >> 36) & 0xf];
  1178. s[7] = digits[(val >> 32) & 0xf];
  1179. s[8] = digits[(val >> 28) & 0xf];
  1180. s[9] = digits[(val >> 24) & 0xf];
  1181. s[10] = digits[(val >> 20) & 0xf];
  1182. s[11] = digits[(val >> 16) & 0xf];
  1183. s[12] = digits[(val >> 12) & 0xf];
  1184. s[13] = digits[(val >> 8) & 0xf];
  1185. s[14] = digits[(val >> 4) & 0xf];
  1186. s[15] = digits[val & 0xf];
  1187. return &s[16];
  1188. }
  1189. static const int char2intarray[] = {
  1190. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1191. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1192. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1193. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
  1194. -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1195. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1196. -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1197. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1198. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1199. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1200. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1201. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1202. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1203. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1204. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1205. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
  1206. };
  1207. int
  1208. slapi_hexchar2int(char c)
  1209. {
  1210. return char2intarray[(unsigned char)c];
  1211. }
  1212. uint8_t
  1213. slapi_str_to_u8(const char *s)
  1214. {
  1215. uint8_t v0 = (uint8_t)slapi_hexchar2int(s[0]);
  1216. uint8_t v1 = (uint8_t)slapi_hexchar2int(s[1]);
  1217. return (v0 << 4) | v1;
  1218. }
  1219. uint16_t
  1220. slapi_str_to_u16(const char *s)
  1221. {
  1222. uint16_t v0 = (uint16_t)slapi_hexchar2int(s[0]);
  1223. uint16_t v1 = (uint16_t)slapi_hexchar2int(s[1]);
  1224. uint16_t v2 = (uint16_t)slapi_hexchar2int(s[2]);
  1225. uint16_t v3 = (uint16_t)slapi_hexchar2int(s[3]);
  1226. return (v0 << 12) | (v1 << 8) | (v2 << 4) | v3;
  1227. }
  1228. uint32_t
  1229. slapi_str_to_u32(const char *s)
  1230. {
  1231. uint32_t v0 = (uint32_t)slapi_hexchar2int(s[0]);
  1232. uint32_t v1 = (uint32_t)slapi_hexchar2int(s[1]);
  1233. uint32_t v2 = (uint32_t)slapi_hexchar2int(s[2]);
  1234. uint32_t v3 = (uint32_t)slapi_hexchar2int(s[3]);
  1235. uint32_t v4 = (uint32_t)slapi_hexchar2int(s[4]);
  1236. uint32_t v5 = (uint32_t)slapi_hexchar2int(s[5]);
  1237. uint32_t v6 = (uint32_t)slapi_hexchar2int(s[6]);
  1238. uint32_t v7 = (uint32_t)slapi_hexchar2int(s[7]);
  1239. return (v0 << 28) | (v1 << 24) | (v2 << 20) | (v3 << 16) | (v4 << 12) | (v5 << 8) | (v6 << 4) | v7;
  1240. }
  1241. uint64_t
  1242. slapi_str_to_u64(const char *s)
  1243. {
  1244. uint64_t v0 = (uint64_t)slapi_hexchar2int(s[0]);
  1245. uint64_t v1 = (uint64_t)slapi_hexchar2int(s[1]);
  1246. uint64_t v2 = (uint64_t)slapi_hexchar2int(s[2]);
  1247. uint64_t v3 = (uint64_t)slapi_hexchar2int(s[3]);
  1248. uint64_t v4 = (uint64_t)slapi_hexchar2int(s[4]);
  1249. uint64_t v5 = (uint64_t)slapi_hexchar2int(s[5]);
  1250. uint64_t v6 = (uint64_t)slapi_hexchar2int(s[6]);
  1251. uint64_t v7 = (uint64_t)slapi_hexchar2int(s[7]);
  1252. uint64_t v8 = (uint64_t)slapi_hexchar2int(s[8]);
  1253. uint64_t v9 = (uint64_t)slapi_hexchar2int(s[9]);
  1254. uint64_t v10 = (uint64_t)slapi_hexchar2int(s[10]);
  1255. uint64_t v11 = (uint64_t)slapi_hexchar2int(s[11]);
  1256. uint64_t v12 = (uint64_t)slapi_hexchar2int(s[12]);
  1257. uint64_t v13 = (uint64_t)slapi_hexchar2int(s[13]);
  1258. uint64_t v14 = (uint64_t)slapi_hexchar2int(s[14]);
  1259. uint64_t v15 = (uint64_t)slapi_hexchar2int(s[15]);
  1260. return (v0 << 60) | (v1 << 56) | (v2 << 52) | (v3 << 48) | (v4 << 44) | (v5 << 40) |
  1261. (v6 << 36) | (v7 << 32) | (v8 << 28) | (v9 << 24) | (v10 << 20) | (v11 << 16) |
  1262. (v12 << 12) | (v13 << 8) | (v14 << 4) | v15;
  1263. }
  1264. /* PR_GetLibraryName does almost everything we need, and unfortunately
  1265. a little bit more - it adds "lib" to be beginning of the library
  1266. name if the library name does not end with the current platform
  1267. DLL suffix - so
  1268. foo.so -> /path/foo.so
  1269. libfoo.so -> /path/libfoo.so
  1270. BUT
  1271. foo -> /path/libfoo.so
  1272. libfoo -> /path/liblibfoo.so
  1273. /path/libfoo -> lib/path/libfoo.so
  1274. */
  1275. char *
  1276. slapi_get_plugin_name(const char *path, const char *lib)
  1277. {
  1278. const char *libstr = "/lib";
  1279. size_t libstrlen = 4;
  1280. char *fullname = PR_GetLibraryName(path, lib);
  1281. char *ptr = PL_strrstr(fullname, lib);
  1282. /* see if /lib was added */
  1283. if (ptr && ((ptr - fullname) >= libstrlen)) {
  1284. /* ptr is at the libname in fullname, and there is something before it */
  1285. ptr -= libstrlen; /* ptr now points at the "/" in "/lib" if it is there */
  1286. if (0 == PL_strncmp(ptr, libstr, libstrlen)) {
  1287. /* just copy the remainder of the string on top of here */
  1288. ptr++; /* ptr now points at the "l" in "/lib" - keep the "/" */
  1289. memmove(ptr, ptr+3, strlen(ptr+3)+1);
  1290. }
  1291. } else if ((NULL == path) && (0 == strncmp(fullname, "lib", 3))) {
  1292. /*
  1293. * case: /path/libfoo -> lib/path/libfoo.so
  1294. * remove "lib".
  1295. */
  1296. memmove(fullname, fullname+3, strlen(fullname)-2);
  1297. }
  1298. return fullname;
  1299. }