softmagic.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /*
  2. * softmagic - interpret variable magic from /etc/magic
  3. *
  4. * Copyright (c) Ian F. Darwin, 1987.
  5. * Written by Ian F. Darwin.
  6. *
  7. * This software is not subject to any license of the American Telephone
  8. * and Telegraph Company or of the Regents of the University of California.
  9. *
  10. * Permission is granted to anyone to use this software for any purpose on
  11. * any computer system, and to alter it and redistribute it freely, subject
  12. * to the following restrictions:
  13. *
  14. * 1. The author is not responsible for the consequences of use of this
  15. * software, no matter how awful, even if they arise from flaws in it.
  16. *
  17. * 2. The origin of this software must not be misrepresented, either by
  18. * explicit claim or by omission. Since few users ever read sources,
  19. * credits must appear in the documentation.
  20. *
  21. * 3. Altered versions must be plainly marked as such, and must not be
  22. * misrepresented as being the original software. Since few users
  23. * ever read sources, credits must appear in the documentation.
  24. *
  25. * 4. This notice may not be removed or altered.
  26. */
  27. #ifdef HAVE_CONFIG_H
  28. #include <config.h>
  29. #endif
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <time.h>
  34. #include <sys/types.h>
  35. #include "file.h"
  36. #ifndef lint
  37. FILE_RCSID("@(#)$Id: softmagic.c,v 1.38 1998/09/12 13:21:01 christos Exp $")
  38. #endif /* lint */
  39. static int match __P((unsigned char *, int));
  40. static int mget __P((union VALUETYPE *,
  41. unsigned char *, struct magic *, int));
  42. static int mcheck __P((union VALUETYPE *, struct magic *));
  43. static int32 mprint __P((union VALUETYPE *, struct magic *));
  44. static void mdebug __P((int32, char *, int));
  45. static int mconvert __P((union VALUETYPE *, struct magic *));
  46. /*
  47. * softmagic - lookup one file in database
  48. * (already read from /etc/magic by apprentice.c).
  49. * Passed the name and FILE * of one file to be typed.
  50. */
  51. /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
  52. int
  53. softmagic(buf, nbytes)
  54. unsigned char *buf;
  55. int nbytes;
  56. {
  57. if (match(buf, nbytes))
  58. return 1;
  59. return 0;
  60. }
  61. /*
  62. * Go through the whole list, stopping if you find a match. Process all
  63. * the continuations of that match before returning.
  64. *
  65. * We support multi-level continuations:
  66. *
  67. * At any time when processing a successful top-level match, there is a
  68. * current continuation level; it represents the level of the last
  69. * successfully matched continuation.
  70. *
  71. * Continuations above that level are skipped as, if we see one, it
  72. * means that the continuation that controls them - i.e, the
  73. * lower-level continuation preceding them - failed to match.
  74. *
  75. * Continuations below that level are processed as, if we see one,
  76. * it means we've finished processing or skipping higher-level
  77. * continuations under the control of a successful or unsuccessful
  78. * lower-level continuation, and are now seeing the next lower-level
  79. * continuation and should process it. The current continuation
  80. * level reverts to the level of the one we're seeing.
  81. *
  82. * Continuations at the current level are processed as, if we see
  83. * one, there's no lower-level continuation that may have failed.
  84. *
  85. * If a continuation matches, we bump the current continuation level
  86. * so that higher-level continuations are processed.
  87. */
  88. static int
  89. match(s, nbytes)
  90. unsigned char *s;
  91. int nbytes;
  92. {
  93. int magindex = 0;
  94. int cont_level = 0;
  95. int need_separator = 0;
  96. union VALUETYPE p;
  97. static int32 *tmpoff = NULL;
  98. static size_t tmplen = 0;
  99. int32 oldoff = 0;
  100. if (tmpoff == NULL)
  101. if ((tmpoff = (int32 *) malloc(tmplen = 20)) == NULL)
  102. error("out of memory\n");
  103. for (magindex = 0; magindex < nmagic; magindex++) {
  104. /* if main entry matches, print it... */
  105. if (!mget(&p, s, &magic[magindex], nbytes) ||
  106. !mcheck(&p, &magic[magindex])) {
  107. /*
  108. * main entry didn't match,
  109. * flush its continuations
  110. */
  111. while (magindex < nmagic &&
  112. magic[magindex + 1].cont_level != 0)
  113. magindex++;
  114. continue;
  115. }
  116. tmpoff[cont_level] = mprint(&p, &magic[magindex]);
  117. /*
  118. * If we printed something, we'll need to print
  119. * a blank before we print something else.
  120. */
  121. if (magic[magindex].desc[0])
  122. need_separator = 1;
  123. /* and any continuations that match */
  124. if (++cont_level >= tmplen)
  125. if ((tmpoff = (int32 *) realloc(tmpoff,
  126. tmplen += 20)) == NULL)
  127. error("out of memory\n");
  128. while (magic[magindex+1].cont_level != 0 &&
  129. ++magindex < nmagic) {
  130. if (cont_level >= magic[magindex].cont_level) {
  131. if (cont_level > magic[magindex].cont_level) {
  132. /*
  133. * We're at the end of the level
  134. * "cont_level" continuations.
  135. */
  136. cont_level = magic[magindex].cont_level;
  137. }
  138. if (magic[magindex].flag & ADD) {
  139. oldoff=magic[magindex].offset;
  140. magic[magindex].offset += tmpoff[cont_level-1];
  141. }
  142. if (mget(&p, s, &magic[magindex], nbytes) &&
  143. mcheck(&p, &magic[magindex])) {
  144. /*
  145. * This continuation matched.
  146. * Print its message, with
  147. * a blank before it if
  148. * the previous item printed
  149. * and this item isn't empty.
  150. */
  151. /* space if previous printed */
  152. if (need_separator
  153. && (magic[magindex].nospflag == 0)
  154. && (magic[magindex].desc[0] != '\0')
  155. ) {
  156. (void) putchar(' ');
  157. need_separator = 0;
  158. }
  159. tmpoff[cont_level] = mprint(&p, &magic[magindex]);
  160. if (magic[magindex].desc[0])
  161. need_separator = 1;
  162. /*
  163. * If we see any continuations
  164. * at a higher level,
  165. * process them.
  166. */
  167. if (++cont_level >= tmplen)
  168. if ((tmpoff =
  169. (int32 *) realloc(tmpoff,
  170. tmplen += 20)) == NULL)
  171. error("out of memory\n");
  172. }
  173. if (magic[magindex].flag & ADD) {
  174. magic[magindex].offset = oldoff;
  175. }
  176. }
  177. }
  178. return 1; /* all through */
  179. }
  180. return 0; /* no match at all */
  181. }
  182. static int32
  183. mprint(p, m)
  184. union VALUETYPE *p;
  185. struct magic *m;
  186. {
  187. char *pp, *rt;
  188. uint32 v;
  189. time_t curtime;
  190. int32 t=0 ;
  191. switch (m->type) {
  192. case BYTE:
  193. v = p->b;
  194. v = signextend(m, v) & m->mask;
  195. (void) printf(m->desc, (unsigned char) v);
  196. t = m->offset + sizeof(char);
  197. break;
  198. case SHORT:
  199. case BESHORT:
  200. case LESHORT:
  201. v = p->h;
  202. v = signextend(m, v) & m->mask;
  203. (void) printf(m->desc, (unsigned short) v);
  204. t = m->offset + sizeof(short);
  205. break;
  206. case LONG:
  207. case BELONG:
  208. case LELONG:
  209. v = p->l;
  210. v = signextend(m, v) & m->mask;
  211. (void) printf(m->desc, (uint32) v);
  212. t = m->offset + sizeof(int32);
  213. break;
  214. case STRING:
  215. if (m->reln == '=') {
  216. (void) printf(m->desc, m->value.s);
  217. t = m->offset + strlen(m->value.s);
  218. }
  219. else {
  220. #ifdef DEBUG_BUG_22854
  221. if (*m->value.s == '\0') {
  222. #else
  223. if (*m->value.s == '\n') {
  224. #endif
  225. char *cp = strchr(p->s,'\n');
  226. if (cp)
  227. *cp = '\0';
  228. }
  229. (void) printf(m->desc, p->s);
  230. t = m->offset + strlen(p->s);
  231. }
  232. break;
  233. case DATE:
  234. case BEDATE:
  235. case LEDATE:
  236. curtime = p->l;
  237. pp = ctime(&curtime);
  238. if ((rt = strchr(pp, '\n')) != NULL)
  239. *rt = '\0';
  240. (void) printf(m->desc, pp);
  241. t = m->offset + sizeof(time_t);
  242. break;
  243. default:
  244. error("invalid m->type (%d) in mprint().\n", m->type);
  245. /*NOTREACHED*/
  246. }
  247. return(t);
  248. }
  249. /*
  250. * Convert the byte order of the data we are looking at
  251. */
  252. static int
  253. mconvert(p, m)
  254. union VALUETYPE *p;
  255. struct magic *m;
  256. {
  257. switch (m->type) {
  258. case BYTE:
  259. case SHORT:
  260. case LONG:
  261. case DATE:
  262. return 1;
  263. case STRING:
  264. {
  265. char *ptr;
  266. /* Null terminate and eat the return */
  267. p->s[sizeof(p->s) - 1] = '\0';
  268. #if DEBIAN_BUG_22854
  269. if ((ptr = strchr(p->s, '\n')) != NULL)
  270. *ptr = '\0';
  271. #endif
  272. return 1;
  273. }
  274. case BESHORT:
  275. p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
  276. return 1;
  277. case BELONG:
  278. case BEDATE:
  279. p->l = (int32)
  280. ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
  281. return 1;
  282. case LESHORT:
  283. p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
  284. return 1;
  285. case LELONG:
  286. case LEDATE:
  287. p->l = (int32)
  288. ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
  289. return 1;
  290. default:
  291. error("invalid type %d in mconvert().\n", m->type);
  292. return 0;
  293. }
  294. }
  295. static void
  296. mdebug(offset, str, len)
  297. int32 offset;
  298. char *str;
  299. int len;
  300. {
  301. (void) fprintf(stderr, "mget @%d: ", offset);
  302. showstr(stderr, (char *) str, len);
  303. (void) fputc('\n', stderr);
  304. (void) fputc('\n', stderr);
  305. }
  306. static int
  307. mget(p, s, m, nbytes)
  308. union VALUETYPE* p;
  309. unsigned char *s;
  310. struct magic *m;
  311. int nbytes;
  312. {
  313. int32 offset = m->offset;
  314. if (offset + sizeof(union VALUETYPE) <= nbytes)
  315. memcpy(p, s + offset, sizeof(union VALUETYPE));
  316. else {
  317. /*
  318. * the usefulness of padding with zeroes eludes me, it
  319. * might even cause problems
  320. */
  321. int32 have = nbytes - offset;
  322. memset(p, 0, sizeof(union VALUETYPE));
  323. if (have > 0)
  324. memcpy(p, s + offset, have);
  325. }
  326. if (debug) {
  327. mdebug(offset, (char *) p, sizeof(union VALUETYPE));
  328. mdump(m);
  329. }
  330. if (m->flag & INDIR) {
  331. switch (m->in.type) {
  332. case BYTE:
  333. offset = p->b + m->in.offset;
  334. break;
  335. case BESHORT:
  336. offset = (short)((p->hs[0]<<8)|(p->hs[1]))+
  337. m->in.offset;
  338. break;
  339. case LESHORT:
  340. offset = (short)((p->hs[1]<<8)|(p->hs[0]))+
  341. m->in.offset;
  342. break;
  343. case SHORT:
  344. offset = p->h + m->in.offset;
  345. break;
  346. case BELONG:
  347. offset = (int32)((p->hl[0]<<24)|(p->hl[1]<<16)|
  348. (p->hl[2]<<8)|(p->hl[3]))+
  349. m->in.offset;
  350. break;
  351. case LELONG:
  352. offset = (int32)((p->hl[3]<<24)|(p->hl[2]<<16)|
  353. (p->hl[1]<<8)|(p->hl[0]))+
  354. m->in.offset;
  355. break;
  356. case LONG:
  357. offset = p->l + m->in.offset;
  358. break;
  359. }
  360. if (offset + sizeof(union VALUETYPE) > nbytes)
  361. return 0;
  362. memcpy(p, s + offset, sizeof(union VALUETYPE));
  363. if (debug) {
  364. mdebug(offset, (char *) p, sizeof(union VALUETYPE));
  365. mdump(m);
  366. }
  367. }
  368. if (!mconvert(p, m))
  369. return 0;
  370. return 1;
  371. }
  372. static int
  373. mcheck(p, m)
  374. union VALUETYPE* p;
  375. struct magic *m;
  376. {
  377. register uint32 l = m->value.l;
  378. register uint32 v;
  379. int matched;
  380. if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
  381. fprintf(stderr, "BOINK");
  382. return 1;
  383. }
  384. switch (m->type) {
  385. case BYTE:
  386. v = p->b;
  387. break;
  388. case SHORT:
  389. case BESHORT:
  390. case LESHORT:
  391. v = p->h;
  392. break;
  393. case LONG:
  394. case BELONG:
  395. case LELONG:
  396. case DATE:
  397. case BEDATE:
  398. case LEDATE:
  399. v = p->l;
  400. break;
  401. case STRING:
  402. l = 0;
  403. /* What we want here is:
  404. * v = strncmp(m->value.s, p->s, m->vallen);
  405. * but ignoring any nulls. bcmp doesn't give -/+/0
  406. * and isn't universally available anyway.
  407. */
  408. v = 0;
  409. {
  410. register unsigned char *a = (unsigned char*)m->value.s;
  411. register unsigned char *b = (unsigned char*)p->s;
  412. register int len = m->vallen;
  413. while (--len >= 0)
  414. if ((v = *b++ - *a++) != '\0')
  415. break;
  416. }
  417. break;
  418. default:
  419. error("invalid type %d in mcheck().\n", m->type);
  420. return 0;/*NOTREACHED*/
  421. }
  422. v = signextend(m, v) & m->mask;
  423. switch (m->reln) {
  424. case 'x':
  425. if (debug)
  426. (void) fprintf(stderr, "%u == *any* = 1\n", v);
  427. matched = 1;
  428. break;
  429. case '!':
  430. matched = v != l;
  431. if (debug)
  432. (void) fprintf(stderr, "%u != %u = %d\n",
  433. v, l, matched);
  434. break;
  435. case '=':
  436. matched = v == l;
  437. if (debug)
  438. (void) fprintf(stderr, "%u == %u = %d\n",
  439. v, l, matched);
  440. break;
  441. case '>':
  442. if (m->flag & UNSIGNED) {
  443. matched = v > l;
  444. if (debug)
  445. (void) fprintf(stderr, "%u > %u = %d\n",
  446. v, l, matched);
  447. }
  448. else {
  449. matched = (int32) v > (int32) l;
  450. if (debug)
  451. (void) fprintf(stderr, "%d > %d = %d\n",
  452. v, l, matched);
  453. }
  454. break;
  455. case '<':
  456. if (m->flag & UNSIGNED) {
  457. matched = v < l;
  458. if (debug)
  459. (void) fprintf(stderr, "%u < %u = %d\n",
  460. v, l, matched);
  461. }
  462. else {
  463. matched = (int32) v < (int32) l;
  464. if (debug)
  465. (void) fprintf(stderr, "%d < %d = %d\n",
  466. v, l, matched);
  467. }
  468. break;
  469. case '&':
  470. matched = (v & l) == l;
  471. if (debug)
  472. (void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
  473. v, l, l, matched);
  474. break;
  475. case '^':
  476. matched = (v & l) != l;
  477. if (debug)
  478. (void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
  479. v, l, l, matched);
  480. break;
  481. default:
  482. matched = 0;
  483. error("mcheck: can't happen: invalid relation %d.\n", m->reln);
  484. break;/*NOTREACHED*/
  485. }
  486. return matched;
  487. }