Skip to content

Commit c745836

Browse files
committed
Added support for robot certificates.
Robot certificates defined by the corresponding IGTF profile are recognized when a chain is being parsed. A new Gridsite certificate type was added to mark the robot in the parsed structures. When the client presents a robot certificate, the Apache module exports a new environment variable (GRST_ROBOT_DN) containg the corresponding subject name of the robot certificate. A simple command that outputs information about a given chain was added.
1 parent 65023e4 commit c745836

File tree

5 files changed

+278
-16
lines changed

5 files changed

+278
-16
lines changed

interface/gridsite.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ typedef struct { int type; /* CA, user, proxy, VOMS, ... */
201201
#define GRST_CERT_TYPE_EEC 2
202202
#define GRST_CERT_TYPE_PROXY 3
203203
#define GRST_CERT_TYPE_VOMS 4
204+
#define GRST_CERT_TYPE_ROBOT 5
204205

205206
/* a chain of certs, starting from the first CA */
206207
typedef struct { GRSTx509Cert *firstcert; } GRSTx509Chain;

src/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ grst_htcp_nossl.lo: grst_htcp.c ../interface/gridsite.h
198198

199199
# now the binary exectuables
200200

201-
gsexec.lo urlencode.lo gridsite-copy.lo findproxyfile.lo showx509exts.lo:
201+
gsexec.lo urlencode.lo gridsite-copy.lo findproxyfile.lo showx509exts.lo test-chain.lo:
202202
$(COMPILE) -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
203203
-o $@ -c $(subst .lo,.c,$@)
204204

@@ -220,6 +220,9 @@ urlencode: urlencode.lo libgridsite.la
220220
htcp: htcp.lo libgridsite.la
221221
$(LINK) -o $@ $+ $(CURL_LIBS)
222222

223+
test-chain: test-chain.lo libgridsite.la
224+
$(LINK) -o $@ $< -L. -lgridsite -static
225+
223226
htcp-static: htcp.lo libgridsite.a
224227
$(LINK) -o $@ -L. $< \
225228
-I/usr/kerberos/include \

src/canl_mod_gridsite.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2498,6 +2498,12 @@ void GRST_save_ssl_creds(conn_rec *conn, GRSTx509Chain *grst_chain)
24982498

24992499
free(encoded);
25002500

2501+
++i;
2502+
}
2503+
else if (grst_cert->type == GRST_CERT_TYPE_ROBOT)
2504+
{
2505+
apr_table_setn(conn->notes, "GRST_ROBOT_DN", apr_pstrdup(conn->pool, grst_cert->dn));
2506+
/* I ignore the sslcreds cache here */
25012507
++i;
25022508
}
25032509
}
@@ -2685,7 +2691,7 @@ static int mod_gridsite_perm_handler(request_rec *r)
26852691
*destination_prefix = NULL, *destination_translated = NULL,
26862692
*aclpath = NULL, *grst_cred_valid_0 = NULL, *grst_cred_valid_i,
26872693
*gridauthpasscode = NULL;
2688-
const char *content_type;
2694+
const char *content_type, *robot;
26892695
time_t notbefore, notafter;
26902696
apr_table_t *env;
26912697
apr_finfo_t cookiefile_info;
@@ -3269,6 +3275,10 @@ static int mod_gridsite_perm_handler(request_rec *r)
32693275
else break;
32703276
}
32713277

3278+
robot = apr_table_get(r->connection->notes, "GRST_ROBOT_DN");
3279+
if (robot)
3280+
apr_table_setn(env, "GRST_ROBOT_DN", robot);
3281+
32723282
apr_table_setn(env, "GRST_PERM", apr_psprintf(r->pool, "%d", perm));
32733283

32743284
if (((mod_gridsite_dir_cfg *) cfg)->requirepasscode == 0)

src/grst_canl_x509.c

Lines changed: 149 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,128 @@
7878
#define GRST_PROXYCACHE "/../proxycache/"
7979
#define GRST_BACKDATE_SECONDS 300
8080

81+
#define END_ENTITY_ROBOT_OID "1.2.840.113612.5.2.3.3.1"
82+
8183
static int GRSTx509CreateProxyRequest_int(char **reqtxt, char **keytxt,
8284
char *ocspurl, int keysize);
8385
static int GRSTx509MakeProxyRequest_int(char **reqtxt, char *proxydir,
8486
char *delegation_id, char *user_dn, int keysize);
8587
static int GRSTx509ProxyKeyMatch(char **pkfile, char *pkdir, STACK_OF(X509) *certstack);
8688

89+
static char *
90+
asn1_string2string(ASN1_STRING *str)
91+
{
92+
BIO *bio;
93+
int len, ret;
94+
char *result = NULL;
95+
96+
bio = BIO_new(BIO_s_mem());
97+
if (bio == NULL)
98+
return NULL;
99+
100+
ASN1_STRING_print_ex(bio, str, ASN1_STRFLGS_RFC2253);
101+
102+
len = BIO_pending(bio);
103+
if (len <= 0)
104+
goto end;
105+
106+
result = calloc(1, len + 1);
107+
if (result == NULL)
108+
goto end;
109+
110+
ret = BIO_read(bio, result, len);
111+
if (ret != len) {
112+
free(result);
113+
result = NULL;
114+
goto end;
115+
}
116+
117+
end:
118+
if (bio)
119+
BIO_free(bio);
120+
121+
return result;
122+
}
123+
124+
static int
125+
is_robot_subject(const char *p)
126+
{
127+
if (strlen(p) <= 6)
128+
return 0;
129+
130+
if (strncmp(p, "Robot", 5) != 0)
131+
return 0;
132+
133+
if (('0' <= p[5] && p[5] <= '9') ||
134+
('A' <= p[5] && p[5] <= 'Z') ||
135+
('a' <= p[5] && p[5] <= 'z'))
136+
return 0;
137+
138+
return 1;
139+
}
140+
141+
static int
142+
is_robot_certificate(X509 *cert)
143+
{
144+
int i, ret, found;
145+
char *p;
146+
char buf[64];
147+
X509_NAME_ENTRY *ne;
148+
X509_NAME *subject;
149+
ASN1_STRING *value;
150+
CERTIFICATEPOLICIES *policies = NULL;
151+
POLICYINFO *policy;
152+
153+
subject = X509_get_subject_name(cert);
154+
if (subject == NULL)
155+
return 0;
156+
157+
found = 0;
158+
i = -1;
159+
while ((i = X509_NAME_get_index_by_NID(subject, NID_commonName, i)) >= 0) {
160+
ne = X509_NAME_get_entry(subject, i);
161+
value = X509_NAME_ENTRY_get_data(ne);
162+
p = asn1_string2string(value);
163+
if (p == NULL)
164+
continue;
165+
ret = is_robot_subject(p);
166+
free(p);
167+
if (ret == 1) {
168+
found = 1;
169+
break;
170+
}
171+
}
172+
if (!found)
173+
return 0;
174+
175+
policies = X509_get_ext_d2i(cert, NID_certificate_policies, &i, NULL);
176+
if (policies == NULL)
177+
return 0;
178+
found = 0;
179+
for (i = 0; i < sk_POLICYINFO_num(policies); i++) {
180+
policy = sk_POLICYINFO_value(policies, i);
181+
memset(buf, 0, sizeof(buf));
182+
OBJ_obj2txt(buf, sizeof(buf), policy->policyid, 1);
183+
if (strcmp(buf, END_ENTITY_ROBOT_OID) == 0) {
184+
found = 1;
185+
break;
186+
}
187+
}
188+
if (!found)
189+
return 0;
190+
191+
return 1;
192+
}
193+
194+
static GRSTx509Cert *
195+
add_grst_cred(GRSTx509Cert *last_cred)
196+
{
197+
GRSTx509Cert *cert;
198+
199+
cert = calloc(1, sizeof(*cert));
200+
return cert;
201+
}
202+
87203
int
88204
GRSTasn1FindField(const char *oid, char *coords,
89205
char *asn1string,
@@ -856,24 +972,29 @@ static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert,
856972

857973
if (itag > -1)
858974
{
859-
(*grst_cert)->next = malloc(sizeof(GRSTx509Cert));
860-
*grst_cert = (*grst_cert)->next;
861-
bzero(*grst_cert, sizeof(GRSTx509Cert));
862-
863-
(*grst_cert)->notbefore = time1_time;
864-
(*grst_cert)->notafter = time2_time;
865-
ret = asprintf(&((*grst_cert)->value), "%.*s",
975+
GRSTx509Cert *cred;
976+
977+
cred = add_grst_cred(*grst_cert);
978+
if (cred == NULL)
979+
return GRST_RET_FAILED;
980+
981+
cred->notbefore = time1_time;
982+
cred->notafter = time2_time;
983+
ret = asprintf(&cred->value, "%.*s",
866984
taglist[itag].length,
867985
&asn1string[taglist[itag].start+
868986
taglist[itag].headerlength]);
869-
if (ret == -1)
987+
if (ret == -1) {
988+
free(cred);
870989
return GRST_RET_FAILED;
871-
872-
(*grst_cert)->errors = chain_errors; /* ie may be invalid */
873-
(*grst_cert)->type = GRST_CERT_TYPE_VOMS;
874-
(*grst_cert)->issuer = strdup(acvomsdn);
875-
(*grst_cert)->dn = strdup(user_cert->dn);
876-
(*grst_cert)->delegation = delegation;
990+
}
991+
cred->errors = chain_errors; /* ie may be invalid */
992+
cred->type = GRST_CERT_TYPE_VOMS;
993+
cred->issuer = strdup(acvomsdn);
994+
cred->dn = strdup(user_cert->dn);
995+
cred->delegation = delegation;
996+
(*grst_cert)->next = cred;
997+
(*grst_cert) = cred;
877998
}
878999
else break;
8791000
}
@@ -906,6 +1027,7 @@ int GRSTx509ChainLoad(GRSTx509Chain **chain,
9061027
X509_EXTENSION *ex;
9071028
time_t now;
9081029
GRSTx509Cert *grst_cert, *new_grst_cert, *user_cert = NULL;
1030+
int is_robot = 0;
9091031

9101032
GRSTerrorLog(GRST_LOG_DEBUG, "GRSTx509ChainLoadCheck() starts");
9111033

@@ -1094,6 +1216,7 @@ int GRSTx509ChainLoad(GRSTx509Chain **chain,
10941216
user_cert = new_grst_cert;
10951217
new_grst_cert->delegation
10961218
= (lastcert == NULL) ? i : i + 1;
1219+
is_robot = is_robot_certificate(cert);
10971220
}
10981221
}
10991222
else
@@ -1170,6 +1293,18 @@ int GRSTx509ChainLoad(GRSTx509Chain **chain,
11701293
} /* end of for loop */
11711294

11721295
if (cacert != NULL) X509_free(cacert);
1296+
1297+
if (is_robot) {
1298+
GRSTx509Cert *cred;
1299+
1300+
cred = add_grst_cred(grst_cert);
1301+
if (cred == NULL)
1302+
return GRST_RET_FAILED;
1303+
cred->type = GRST_CERT_TYPE_ROBOT;
1304+
cred->dn = strdup(user_cert->dn);
1305+
grst_cert->next = cred;
1306+
grst_cert = cred;
1307+
}
11731308

11741309
return GRST_RET_OK;
11751310
}

src/test-chain.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <errno.h>
5+
#include <getopt.h>
6+
#include <openssl/err.h>
7+
8+
#include <gridsite.h>
9+
10+
int main(int argc, char *argv[])
11+
{
12+
FILE *fp = NULL;
13+
int ret = 0;
14+
int ptrlen, i;
15+
char *ptr, *tmp, *p;
16+
char c;
17+
char *chain = argv[1];
18+
STACK_OF(X509) *x509_certstack;
19+
char *vomsdir = "/etc/grid-security/vomsdir";
20+
char *capath = "/etc/grid-security/certificates";
21+
GRSTx509Cert *grst_cert = NULL;
22+
GRSTx509Chain *grst_chain = NULL;
23+
24+
fp = fopen(chain, "r");
25+
if (fp == NULL) {
26+
fprintf(stderr, "Failed to open %s: %s\n", chain, strerror(errno));
27+
ret = 1;
28+
goto end;
29+
}
30+
31+
ptrlen = 4096;
32+
ptr = malloc(ptrlen);
33+
i = 0;
34+
while ((c = fgetc(fp)) != EOF) {
35+
ptr[i] = c;
36+
++i;
37+
38+
if (i >= ptrlen) {
39+
ptrlen += 4096;
40+
tmp = realloc(ptr, ptrlen);
41+
if (tmp == NULL) {
42+
fprintf(stderr, "Not enough memory, exiting\n");
43+
free(ptr);
44+
ret = 1;
45+
goto end;
46+
}
47+
ptr = tmp;
48+
}
49+
}
50+
fclose(fp);
51+
fp = NULL;
52+
ptr[i] = '\0';
53+
54+
ret = GRSTx509StringToChain(&x509_certstack, ptr);
55+
free(ptr);
56+
if (ret != GRST_RET_OK || x509_certstack == NULL) {
57+
fprintf(stderr, "Failed to parse proxy file for certificate chain\n");
58+
ret = 1;
59+
goto end;
60+
}
61+
62+
ret = GRSTx509ChainLoadCheck(&grst_chain, x509_certstack, NULL,
63+
capath, vomsdir);
64+
if ((ret != GRST_RET_OK) ||
65+
(grst_chain == NULL) || (grst_chain->firstcert == NULL)) {
66+
fprintf(stderr, "Failed parsing certificate chain\n");
67+
ret = 1;
68+
goto end;
69+
}
70+
71+
grst_cert = grst_chain->firstcert;
72+
for (i=0; grst_cert != NULL; grst_cert = grst_cert->next, ++i) {
73+
if (grst_cert->type == GRST_CERT_TYPE_CA) p = "(CA) ";
74+
else if (grst_cert->type == GRST_CERT_TYPE_EEC) p = "(EEC) ";
75+
else if (grst_cert->type == GRST_CERT_TYPE_PROXY) p = "(PC) ";
76+
else if (grst_cert->type == GRST_CERT_TYPE_VOMS) p = "(AC) ";
77+
else if (grst_cert->type == GRST_CERT_TYPE_ROBOT) p = "(ROBOT) ";
78+
else p = "";
79+
80+
printf("%d %s%s\n", i, p,
81+
(grst_cert->type == GRST_CERT_TYPE_VOMS)
82+
? grst_cert->value : grst_cert->dn);
83+
84+
printf(" Status : %d ( %s%s%s%s%s%s)\n", grst_cert->errors,
85+
(grst_cert->errors == 0) ? "OK " : "",
86+
(grst_cert->errors & GRST_CERT_BAD_FORMAT) ? "BAD_FORMAT ":"",
87+
(grst_cert->errors & GRST_CERT_BAD_CHAIN) ? "BAD_CHAIN ":"",
88+
(grst_cert->errors & GRST_CERT_BAD_SIG) ? "BAD_SIG ":"",
89+
(grst_cert->errors & GRST_CERT_BAD_TIME) ? "BAD_TIME ":"",
90+
(grst_cert->errors & GRST_CERT_BAD_OCSP) ? "BAD_OCSP ":"");
91+
92+
printf(" Start : %s", ctime(&(grst_cert->notbefore)));
93+
printf(" Finish : %s", ctime(&(grst_cert->notafter)));
94+
printf(" Delegation : %d\n", grst_cert->delegation);
95+
96+
if (grst_cert->type == GRST_CERT_TYPE_VOMS) {
97+
printf(" User DN : %s\n", grst_cert->dn);
98+
printf(" VOMS DN : %s\n\n", grst_cert->issuer);
99+
} else {
100+
printf(" Serial : %s\n", grst_cert->serial);
101+
printf(" Issuer : %s\n\n", grst_cert->issuer);
102+
}
103+
}
104+
GRSTx509ChainFree(grst_chain);
105+
106+
ret = 0;
107+
108+
end:
109+
if (fp)
110+
fclose(fp);
111+
112+
return ret;
113+
}

0 commit comments

Comments
 (0)