chiark / gitweb /
configure.ac: Replace with a new version.
[catacomb] / key-flags.c
1 /* -*-c-*-
2  *
3  * $Id$
4  *
5  * Reading and writing key flag strings
6  *
7  * (c) 1999 Straylight/Edgeware
8  */
9
10 /*----- Licensing notice --------------------------------------------------*
11  *
12  * This file is part of Catacomb.
13  *
14  * Catacomb is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU Library General Public License as
16  * published by the Free Software Foundation; either version 2 of the
17  * License, or (at your option) any later version.
18  *
19  * Catacomb is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with Catacomb; if not, write to the Free
26  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27  * MA 02111-1307, USA.
28  */
29
30 /*----- Header files ------------------------------------------------------*/
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <mLib/bits.h>
36 #include <mLib/dstr.h>
37
38 #include "key-data.h"
39
40 /*----- Data structures ---------------------------------------------------*/
41
42 typedef struct key_flags {
43   unsigned f;
44   unsigned m;
45 } key_flags;
46
47 /*----- Flags table -------------------------------------------------------*/
48
49 typedef struct flagent {
50   const char *name;
51   unsigned f;
52   unsigned m;
53 } flagent;
54
55 static const flagent flagtab[] = {
56
57   /* --- Encoding types --- */
58
59   { "binary",           KENC_BINARY,    KF_ENCMASK },
60   { "integer",          KENC_MP,        KF_ENCMASK },
61   { "struct",           KENC_STRUCT,    KF_ENCMASK },
62   { "encrypt",          KENC_ENCRYPT,   KF_ENCMASK },
63   { "string",           KENC_STRING,    KF_ENCMASK },
64   { "ec",               KENC_EC,        KF_ENCMASK },
65
66   /* --- Classes of keys --- */
67
68   { "shared",           KCAT_SHARE,     KF_CATMASK },
69   { "public",           KCAT_PUB,       KF_CATMASK },
70   { "private",          KCAT_PRIV,      KF_CATMASK },
71   { "symmetric",        KCAT_SYMM,      KF_CATMASK },
72   { "secret",           0,              KF_NONSECRET },
73   { "-secret",          KF_NONSECRET,   KF_NONSECRET },
74
75   /* --- Other flags --- */
76
77   { "burn",             KF_BURN,        KF_BURN },
78   { "-burn",            0,              KF_BURN },
79
80   /* --- End marker --- */
81
82   { 0,                  0,              0 }
83 };
84
85 /*----- Main code ---------------------------------------------------------*/
86
87 /* --- @key_readflags@ --- *
88  *
89  * Arguments:   @const char *p@ = pointer to string to read
90  *              @char **pp@ = where to store the end pointer
91  *              @unsigned *ff@ = where to store the flags
92  *              @unsigned *mm@ = where to store the mask
93  *
94  * Returns:     Zero if all went well, nonzero if there was an error.
95  *
96  * Use:         Reads a flag string.
97  */
98
99 int key_readflags(const char *p, char **pp, unsigned *ff, unsigned *mm)
100 {
101   unsigned f = 0, m = 0;
102
103   for (;;) {
104     size_t sz = strcspn(p, ",:");
105     const flagent *e, *ee = 0;
106
107     /* --- Look up the string in the flags table --- */
108
109     if (sz == 4 && strncmp(p, "none", 4) == 0)
110       goto next;
111     for (e = flagtab; e->name; e++) {
112       if (strncmp(e->name, p, sz) == 0) {
113         if (e->name[sz] == 0) {
114           ee = e;
115           break;
116         } else if (ee)
117           return (KERR_BADFLAGS);
118         else
119           ee = e;
120       }
121     }
122     if (!ee)
123       return (KERR_BADFLAGS);
124
125     /* --- Adjust the flag words --- *
126      *
127      * Ensure that the flags set are disjoint.
128      */
129
130     if (m & ee->m)
131       return (KERR_BADFLAGS);
132     m |= ee->m;
133     f |= ee->f;
134   next:
135     p += sz;
136     if (*p == 0 || *p == ':')
137       break;
138     p++;
139   }
140
141   /* --- Report the results --- */
142
143   if (ff) *ff = f;
144   if (mm) *mm = m;
145   if (pp) *pp = (char *)p;
146   return (0);
147 }
148
149 /* --- @key_writeflags@ --- *
150  *
151  * Arguments:   @unsigned f@ = flags to write
152  *              @dstr *d@ = pointer to destination string
153  *
154  * Returns:     ---
155  *
156  * Use:         Emits a flags word as a string representation.
157  */
158
159 void key_writeflags(unsigned f, dstr *d)
160 {
161   int del = 0;
162   const flagent *e;
163   unsigned m = 0;
164
165   for (e = flagtab; e->name; e++) {
166     if (m & e->m || e->name[0] == '-' || (f & e->m) != e->f)
167       continue;
168     if (del)
169       DPUTC(d, ',');
170     DPUTS(d, e->name);
171     m |= e->m;
172     del = 1;
173   }
174 }
175
176 /* --- @key_match@ --- *
177  *
178  * Arguments:   @key_data *k@ = pointer to key data block
179  *              @const key_filter *kf@ = pointer to filter block
180  *
181  * Returns:     Nonzero if the key matches the filter.
182  *
183  * Use:         Checks whether a key matches a filter.
184  */
185
186 int key_match(key_data *k, const key_filter *kf)
187 {
188   key_subkeyiter i;
189   const char *tag;
190   key_data *kd;
191
192   if (!kf)
193     return (1);
194   if ((k->e & KF_ENCMASK) != KENC_STRUCT)
195     return ((k->e & kf->m) == kf->f);
196
197   for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) {
198     if (key_match(kd, kf))
199       return (1);
200   }
201   return (0);
202 }
203
204 /*----- That's all, folks -------------------------------------------------*/