rpmcliSign() only creates or deletes signatures
[platform/upstream/rpm.git] / rpmqv.c
1 #include "system.h"
2 const char *__progname;
3
4 #include <rpm/rpmcli.h>
5 #include <rpm/rpmlib.h>                 /* RPMSIGTAG, rpmReadPackageFile .. */
6 #include <rpm/rpmbuild.h>
7 #include <rpm/rpmlog.h>
8 #include <rpm/rpmdb.h>
9 #include <rpm/rpmps.h>
10 #include <rpm/rpmts.h>
11
12 #if defined(IAM_RPMK)
13 #include "lib/signature.h"
14 #endif
15 #include "cliutils.h"
16
17 #include "debug.h"
18
19 enum modes {
20
21     MODE_QUERY          = (1 <<  0),
22     MODE_VERIFY         = (1 <<  3),
23 #define MODES_QV (MODE_QUERY | MODE_VERIFY)
24
25     MODE_INSTALL        = (1 <<  1),
26     MODE_ERASE          = (1 <<  2),
27 #define MODES_IE (MODE_INSTALL | MODE_ERASE)
28
29     MODE_CHECKSIG       = (1 <<  6),
30     MODE_RESIGN         = (1 <<  7),
31     MODE_KEYRING        = (1 <<  8),
32 #define MODES_K  (MODE_CHECKSIG | MODE_RESIGN | MODE_KEYRING)
33
34     MODE_INITDB         = (1 << 10),
35     MODE_REBUILDDB      = (1 << 12),
36     MODE_VERIFYDB       = (1 << 13),
37 #define MODES_DB (MODE_INITDB | MODE_REBUILDDB | MODE_VERIFYDB)
38
39
40     MODE_UNKNOWN        = 0
41 };
42
43 #define MODES_FOR_DBPATH        (MODES_IE | MODES_QV | MODES_DB)
44 #define MODES_FOR_NODEPS        (MODES_IE | MODE_VERIFY)
45 #define MODES_FOR_TEST          (MODES_IE)
46 #define MODES_FOR_ROOT          (MODES_IE | MODES_QV | MODES_DB | MODES_K)
47
48 static int quiet;
49
50 /* the structure describing the options we take and the defaults */
51 static struct poptOption optionsTable[] = {
52
53 #ifdef  IAM_RPMQV
54  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmQVSourcePoptTable, 0,
55         N_("Query/Verify package selection options:"),
56         NULL },
57  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmQueryPoptTable, 0,
58         N_("Query options (with -q or --query):"),
59         NULL },
60  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmVerifyPoptTable, 0,
61         N_("Verify options (with -V or --verify):"),
62         NULL },
63 #endif  /* IAM_RPMQV */
64
65 #ifdef  IAM_RPMK
66  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmSignPoptTable, 0,
67         N_("Signature options:"),
68         NULL },
69 #endif  /* IAM_RPMK */
70
71 #ifdef  IAM_RPMDB
72  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmDatabasePoptTable, 0,
73         N_("Database options:"),
74         NULL },
75 #endif  /* IAM_RPMDB */
76
77 #ifdef  IAM_RPMEIU
78  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmInstallPoptTable, 0,
79         N_("Install/Upgrade/Erase options:"),
80         NULL },
81 #endif  /* IAM_RPMEIU */
82
83  { "quiet", '\0', POPT_ARGFLAG_DOC_HIDDEN, &quiet, 0, NULL, NULL},
84
85  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
86         N_("Common options for all rpm modes and executables:"),
87         NULL },
88
89    POPT_AUTOALIAS
90    POPT_AUTOHELP
91    POPT_TABLEEND
92 };
93
94 int main(int argc, char *argv[])
95 {
96     rpmts ts = NULL;
97     enum modes bigMode = MODE_UNKNOWN;
98
99 #if defined(IAM_RPMQV)
100     QVA_t qva = &rpmQVKArgs;
101 #endif
102
103 #ifdef  IAM_RPMEIU
104    struct rpmInstallArguments_s * ia = &rpmIArgs;
105 #endif
106
107 #if defined(IAM_RPMDB)
108    struct rpmDatabaseArguments_s * da = &rpmDBArgs;
109 #endif
110
111 #if defined(IAM_RPMK)
112    QVA_t ka = &rpmQVKArgs;
113 #endif
114
115 #if defined(IAM_RPMK)
116     char * passPhrase = "";
117 #endif
118
119     poptContext optCon;
120     int ec = 0;
121 #ifdef  IAM_RPMEIU
122     int i;
123 #endif
124
125     optCon = rpmcliInit(argc, argv, optionsTable);
126
127     /* Set the major mode based on argv[0] */
128 #ifdef  IAM_RPMQV
129     if (rstreq(__progname, "rpmquery")) bigMode = MODE_QUERY;
130     if (rstreq(__progname, "rpmverify")) bigMode = MODE_VERIFY;
131 #endif
132
133 #if defined(IAM_RPMQV)
134     /* Jumpstart option from argv[0] if necessary. */
135     switch (bigMode) {
136     case MODE_QUERY:    qva->qva_mode = 'q';    break;
137     case MODE_VERIFY:   qva->qva_mode = 'V';    break;
138     case MODE_CHECKSIG: qva->qva_mode = 'K';    break;
139     case MODE_RESIGN:   qva->qva_mode = 'R';    break;
140     case MODE_INSTALL:
141     case MODE_ERASE:
142     case MODE_INITDB:
143     case MODE_REBUILDDB:
144     case MODE_VERIFYDB:
145     case MODE_UNKNOWN:
146     default:
147         break;
148     }
149 #endif
150
151 #ifdef  IAM_RPMDB
152   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_DB)) {
153     if (da->init) {
154         if (bigMode != MODE_UNKNOWN) 
155             argerror(_("only one major mode may be specified"));
156         else
157             bigMode = MODE_INITDB;
158     } else
159     if (da->rebuild) {
160         if (bigMode != MODE_UNKNOWN) 
161             argerror(_("only one major mode may be specified"));
162         else
163             bigMode = MODE_REBUILDDB;
164     } else
165     if (da->verify) {
166         if (bigMode != MODE_UNKNOWN) 
167             argerror(_("only one major mode may be specified"));
168         else
169             bigMode = MODE_VERIFYDB;
170     }
171   }
172 #endif  /* IAM_RPMDB */
173
174 #ifdef  IAM_RPMQV
175   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_QV)) {
176     switch (qva->qva_mode) {
177     case 'q':   bigMode = MODE_QUERY;           break;
178     case 'V':   bigMode = MODE_VERIFY;          break;
179     }
180
181     if (qva->qva_sourceCount) {
182         if (qva->qva_sourceCount > 2)
183             argerror(_("one type of query/verify may be performed at a "
184                         "time"));
185     }
186     if (qva->qva_flags && (bigMode & ~MODES_QV)) 
187         argerror(_("unexpected query flags"));
188
189     if (qva->qva_queryFormat && (bigMode & ~MODES_QV)) 
190         argerror(_("unexpected query format"));
191
192     if (qva->qva_source != RPMQV_PACKAGE && (bigMode & ~MODES_QV)) 
193         argerror(_("unexpected query source"));
194   }
195 #endif  /* IAM_RPMQV */
196
197 #ifdef  IAM_RPMEIU
198   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_IE))
199     {   int iflags = (ia->installInterfaceFlags &
200                 (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL));
201         int eflags = (ia->installInterfaceFlags & INSTALL_ERASE);
202
203         if (iflags & eflags)
204             argerror(_("only one major mode may be specified"));
205         else if (iflags)
206             bigMode = MODE_INSTALL;
207         else if (eflags)
208             bigMode = MODE_ERASE;
209     }
210 #endif  /* IAM_RPMEIU */
211
212 #ifdef  IAM_RPMK
213   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_K)) {
214         switch (ka->qva_mode) {
215         case RPMSIGN_IMPORT_PUBKEY:
216             bigMode = MODE_KEYRING;
217             break;
218         case RPMSIGN_CHK_SIGNATURE:
219             bigMode = MODE_CHECKSIG;
220             break;
221         case RPMSIGN_ADD_SIGNATURE:
222         case RPMSIGN_NEW_SIGNATURE:
223             ka->sign = 1;
224             /* fallthrough */
225         case RPMSIGN_DEL_SIGNATURE:
226             bigMode = MODE_RESIGN;
227             break;
228         }
229   }
230 #endif  /* IAM_RPMK */
231
232 #if defined(IAM_RPMEIU)
233     if (!( bigMode == MODE_INSTALL ) &&
234 (ia->probFilter & (RPMPROB_FILTER_REPLACEPKG | RPMPROB_FILTER_OLDPACKAGE)))
235         argerror(_("only installation, upgrading, rmsource and rmspec may be forced"));
236     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_FORCERELOCATE))
237         argerror(_("files may only be relocated during package installation"));
238
239     if (ia->relocations && ia->prefix)
240         argerror(_("cannot use --prefix with --relocate or --excludepath"));
241
242     if (bigMode != MODE_INSTALL && ia->relocations)
243         argerror(_("--relocate and --excludepath may only be used when installing new packages"));
244
245     if (bigMode != MODE_INSTALL && ia->prefix)
246         argerror(_("--prefix may only be used when installing new packages"));
247
248     if (ia->prefix && ia->prefix[0] != '/') 
249         argerror(_("arguments to --prefix must begin with a /"));
250
251     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_HASH))
252         argerror(_("--hash (-h) may only be specified during package "
253                         "installation"));
254
255     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_PERCENT))
256         argerror(_("--percent may only be specified during package "
257                         "installation"));
258
259     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_REPLACEPKG))
260         argerror(_("--replacepkgs may only be specified during package "
261                         "installation"));
262
263     if (bigMode != MODE_INSTALL && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
264         argerror(_("--excludedocs may only be specified during package "
265                    "installation"));
266
267     if (bigMode != MODE_INSTALL && ia->incldocs)
268         argerror(_("--includedocs may only be specified during package "
269                    "installation"));
270
271     if (ia->incldocs && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
272         argerror(_("only one of --excludedocs and --includedocs may be "
273                  "specified"));
274   
275     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREARCH))
276         argerror(_("--ignorearch may only be specified during package "
277                    "installation"));
278
279     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREOS))
280         argerror(_("--ignoreos may only be specified during package "
281                    "installation"));
282
283     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
284         (ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES)))
285         argerror(_("--ignoresize may only be specified during package "
286                    "installation"));
287
288     if ((ia->installInterfaceFlags & UNINSTALL_ALLMATCHES) && bigMode != MODE_ERASE)
289         argerror(_("--allmatches may only be specified during package "
290                    "erasure"));
291
292     if ((ia->transFlags & RPMTRANS_FLAG_ALLFILES) && bigMode != MODE_INSTALL)
293         argerror(_("--allfiles may only be specified during package "
294                    "installation"));
295
296     if ((ia->transFlags & RPMTRANS_FLAG_JUSTDB) &&
297         bigMode != MODE_INSTALL && bigMode != MODE_ERASE)
298         argerror(_("--justdb may only be specified during package "
299                    "installation and erasure"));
300
301     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE && bigMode != MODE_VERIFY &&
302         (ia->transFlags & (RPMTRANS_FLAG_NOSCRIPTS | _noTransScripts | _noTransTriggers)))
303         argerror(_("script disabling options may only be specified during "
304                    "package installation and erasure"));
305
306     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE && bigMode != MODE_VERIFY &&
307         (ia->transFlags & (RPMTRANS_FLAG_NOTRIGGERS | _noTransTriggers)))
308         argerror(_("trigger disabling options may only be specified during "
309                    "package installation and erasure"));
310
311     if (ia->noDeps & (bigMode & ~MODES_FOR_NODEPS))
312         argerror(_("--nodeps may only be specified during package "
313                    "building, rebuilding, recompilation, installation,"
314                    "erasure, and verification"));
315
316     if ((ia->transFlags & RPMTRANS_FLAG_TEST) && (bigMode & ~MODES_FOR_TEST))
317         argerror(_("--test may only be specified during package installation, "
318                  "erasure, and building"));
319 #endif  /* IAM_RPMEIU */
320
321     if (rpmcliRootDir && rpmcliRootDir[1] && (bigMode & ~MODES_FOR_ROOT))
322         argerror(_("--root (-r) may only be specified during "
323                  "installation, erasure, querying, and "
324                  "database rebuilds"));
325
326     if (rpmcliRootDir && rpmcliRootDir[0] != '/') {
327         argerror(_("arguments to --root (-r) must begin with a /"));
328     }
329
330     if (quiet)
331         rpmSetVerbosity(RPMLOG_WARNING);
332
333 #if defined(IAM_RPMK)
334     if (ka->sign) {
335         if (bigMode == MODE_RESIGN) {
336             const char ** av;
337             struct stat sb;
338             int errors = 0;
339
340             if ((av = poptGetArgs(optCon)) == NULL) {
341                 fprintf(stderr, _("no files to sign\n"));
342                 errors++;
343             } else
344             while (*av) {
345                 if (stat(*av, &sb)) {
346                     fprintf(stderr, _("cannot access file %s\n"), *av);
347                     errors++;
348                 }
349                 av++;
350             }
351
352             if (errors) {
353                 ec = errors;
354                 goto exit;
355             }
356
357             if (poptPeekArg(optCon)) {
358                 int sigTag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY);
359                 switch (sigTag) {
360                   case 0:
361                     break;
362                   case RPMSIGTAG_PGP:
363                   case RPMSIGTAG_GPG:
364                   case RPMSIGTAG_DSA:
365                   case RPMSIGTAG_RSA:
366                     passPhrase = rpmGetPassPhrase(_("Enter pass phrase: "), sigTag);
367                     if (passPhrase == NULL) {
368                         fprintf(stderr, _("Pass phrase check failed\n"));
369                         ec = EXIT_FAILURE;
370                         goto exit;
371                     }
372                     fprintf(stderr, _("Pass phrase is good.\n"));
373                     passPhrase = xstrdup(passPhrase);
374                     break;
375                   default:
376                     fprintf(stderr,
377                             _("Invalid %%_signature spec in macro file.\n"));
378                     ec = EXIT_FAILURE;
379                     goto exit;
380                     break;
381                 }
382             }
383         } else {
384             argerror(_("--sign may only be used during package building"));
385         }
386     } else {
387         /* Make rpmLookupSignatureType() return 0 ("none") from now on */
388         (void) rpmLookupSignatureType(RPMLOOKUPSIG_DISABLE);
389     }
390 #endif  /* IAM_RPMK */
391
392     if (rpmcliPipeOutput && initPipe())
393         exit(EXIT_FAILURE);
394         
395     ts = rpmtsCreate();
396     (void) rpmtsSetRootDir(ts, rpmcliRootDir);
397     switch (bigMode) {
398 #ifdef  IAM_RPMDB
399     case MODE_INITDB:
400         ec = rpmtsInitDB(ts, 0644);
401         break;
402
403     case MODE_REBUILDDB:
404     {   rpmVSFlags vsflags = rpmExpandNumeric("%{_vsflags_rebuilddb}");
405         rpmVSFlags ovsflags = rpmtsSetVSFlags(ts, vsflags);
406         ec = rpmtsRebuildDB(ts);
407         vsflags = rpmtsSetVSFlags(ts, ovsflags);
408     }   break;
409     case MODE_VERIFYDB:
410         ec = rpmtsVerifyDB(ts);
411         break;
412 #endif  /* IAM_RPMDB */
413
414 #ifdef  IAM_RPMEIU
415     case MODE_ERASE:
416         if (ia->noDeps) ia->installInterfaceFlags |= UNINSTALL_NODEPS;
417
418         if (!poptPeekArg(optCon)) {
419             argerror(_("no packages given for erase"));
420         } else {
421             ec += rpmErase(ts, ia, (ARGV_const_t) poptGetArgs(optCon));
422         }
423         break;
424
425     case MODE_INSTALL:
426
427         /* RPMTRANS_FLAG_KEEPOBSOLETE */
428
429         if (!ia->incldocs) {
430             if (ia->transFlags & RPMTRANS_FLAG_NODOCS) {
431                 ;
432             } else if (rpmExpandNumeric("%{_excludedocs}"))
433                 ia->transFlags |= RPMTRANS_FLAG_NODOCS;
434         }
435
436         if (ia->noDeps) ia->installInterfaceFlags |= INSTALL_NODEPS;
437
438         /* we've already ensured !(!ia->prefix && !ia->relocations) */
439         if (ia->prefix) {
440             ia->relocations = xmalloc(2 * sizeof(*ia->relocations));
441             ia->relocations[0].oldPath = NULL;   /* special case magic */
442             ia->relocations[0].newPath = ia->prefix;
443             ia->relocations[1].oldPath = NULL;
444             ia->relocations[1].newPath = NULL;
445         } else if (ia->relocations) {
446             ia->relocations = xrealloc(ia->relocations, 
447                         sizeof(*ia->relocations) * (ia->numRelocations + 1));
448             ia->relocations[ia->numRelocations].oldPath = NULL;
449             ia->relocations[ia->numRelocations].newPath = NULL;
450         }
451
452         if (!poptPeekArg(optCon)) {
453             argerror(_("no packages given for install"));
454         } else {
455             /* FIX: ia->relocations[0].newPath undefined */
456             ec += rpmInstall(ts, ia, (ARGV_t) poptGetArgs(optCon));
457         }
458         break;
459
460 #endif  /* IAM_RPMEIU */
461
462 #ifdef  IAM_RPMQV
463     case MODE_QUERY:
464         if (!poptPeekArg(optCon) && !(qva->qva_source == RPMQV_ALL))
465             argerror(_("no arguments given for query"));
466
467         qva->qva_specQuery = rpmspecQuery;
468         ec = rpmcliQuery(ts, qva, (ARGV_const_t) poptGetArgs(optCon));
469         qva->qva_specQuery = NULL;
470         break;
471
472     case MODE_VERIFY:
473     {   rpmVerifyFlags verifyFlags = VERIFY_ALL;
474
475         verifyFlags &= ~qva->qva_flags;
476         qva->qva_flags = (rpmQueryFlags) verifyFlags;
477
478         if (!poptPeekArg(optCon) && !(qva->qva_source == RPMQV_ALL))
479             argerror(_("no arguments given for verify"));
480         ec = rpmcliVerify(ts, qva, (ARGV_const_t) poptGetArgs(optCon));
481     }   break;
482 #endif  /* IAM_RPMQV */
483
484 #ifdef IAM_RPMK
485     case MODE_KEYRING:
486         if (!poptPeekArg(optCon))
487             argerror(_("no arguments given"));
488         ec = rpmcliImportPubkeys(ts, (ARGV_const_t) poptGetArgs(optCon));
489         break;
490     case MODE_CHECKSIG:
491     {   rpmVerifyFlags verifyFlags =
492                 (VERIFY_FILEDIGEST|VERIFY_DIGEST|VERIFY_SIGNATURE);
493
494         verifyFlags &= ~rpmcliQueryFlags;
495         ka->qva_flags = (rpmQueryFlags) verifyFlags;
496         ec = rpmcliVerifySignatures(ts, ka, (ARGV_const_t) poptGetArgs(optCon));
497         break;
498     }  
499     case MODE_RESIGN:
500         if (!poptPeekArg(optCon))
501             argerror(_("no arguments given"));
502         ec = rpmcliSign((ARGV_const_t) poptGetArgs(optCon),
503                         (qva->qva_mode == RPMSIGN_DEL_SIGNATURE), passPhrase);
504         break;
505 #endif  /* IAM_RPMK */
506         
507 #if !defined(IAM_RPMQV)
508     case MODE_QUERY:
509     case MODE_VERIFY:
510 #endif
511 #if !defined(IAM_RPMK)
512     case MODE_CHECKSIG:
513     case MODE_RESIGN:
514 #endif
515 #if !defined(IAM_RPMDB)
516     case MODE_INITDB:
517     case MODE_REBUILDDB:
518     case MODE_VERIFYDB:
519 #endif
520 #if !defined(IAM_RPMEIU)
521     case MODE_INSTALL:
522     case MODE_ERASE:
523 #endif
524     case MODE_UNKNOWN:
525         if (poptPeekArg(optCon) != NULL || argc <= 1 || rpmIsVerbose()) {
526             printUsage(optCon, stderr, 0);
527             ec = argc;
528         }
529         break;
530     }
531
532 exit:
533     ts = rpmtsFree(ts);
534     finishPipe();
535
536 #ifdef  IAM_RPMQV
537     qva->qva_queryFormat = _free(qva->qva_queryFormat);
538 #endif
539
540 #ifdef  IAM_RPMEIU
541     if (ia->relocations != NULL)
542     for (i = 0; i < ia->numRelocations; i++)
543         ia->relocations[i].oldPath = _free(ia->relocations[i].oldPath);
544     ia->relocations = _free(ia->relocations);
545 #endif
546
547     rpmcliFini(optCon);
548
549     return RETVAL(ec);
550 }