diff options
-rw-r--r-- | keyserver/ChangeLog | 8 | ||||
-rw-r--r-- | keyserver/gpgkeys_ldap.c | 81 |
2 files changed, 70 insertions, 19 deletions
diff --git a/keyserver/ChangeLog b/keyserver/ChangeLog index e364daf31..1780d3717 100644 --- a/keyserver/ChangeLog +++ b/keyserver/ChangeLog @@ -1,3 +1,11 @@ +2004-07-28 David Shaw <[email protected]> + + * gpgkeys_ldap.c (join_two_modlists): New. + (send_key): Use new function so we can try a modify operation + first, and fail over to an add if that fails. Add cannot cope + with the NULLs at the head of the modify request, so we jump into + the list in the middle. + 2004-07-27 David Shaw <[email protected]> * gpgkeys_ldap.c (main): Don't try and error out before making a diff --git a/keyserver/gpgkeys_ldap.c b/keyserver/gpgkeys_ldap.c index 9db0026c8..8d1014179 100644 --- a/keyserver/gpgkeys_ldap.c +++ b/keyserver/gpgkeys_ldap.c @@ -220,6 +220,34 @@ epoch2ldaptime(time_t stamp) return strdup(buf); } +/* Append two onto the end of one. Two is not freed, but its pointers + are now part of one. Make sure you don't free them both! */ +static int +join_two_modlists(LDAPMod ***one,LDAPMod **two) +{ + int i,one_count=0,two_count=0; + LDAPMod **grow; + + for(grow=*one;*grow;grow++) + one_count++; + + for(grow=two;*grow;grow++) + two_count++; + + grow=realloc(*one,sizeof(LDAPMod *)*(one_count+two_count+1)); + if(!grow) + return 0; + + for(i=0;i<two_count;i++) + grow[one_count+i]=two[i]; + + grow[one_count+i]=NULL; + + *one=grow; + + return 1; +} + /* Passing a NULL for value effectively deletes that attribute. This doesn't mean "delete" in the sense of removing something from the modlist, but "delete" in the LDAP sense of adding a modlist item @@ -505,7 +533,7 @@ send_key(int *eof) int err,begin=0,end=0,keysize=1,ret=KEYSERVER_INTERNAL_ERROR; char *dn=NULL,line[MAX_LINE],*key=NULL; char keyid[17]; - LDAPMod **modlist,**ml; + LDAPMod **modlist,**addlist,**ml; modlist=malloc(sizeof(LDAPMod *)); if(!modlist) @@ -517,8 +545,19 @@ send_key(int *eof) *modlist=NULL; - /* Going on the assumption that modify operations are more frequent - than adds, I'm setting up the modify operations here first. */ + addlist=malloc(sizeof(LDAPMod *)); + if(!addlist) + { + fprintf(console,"gpgkeys: can't allocate memory for keyserver record\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + *addlist=NULL; + + /* Start by nulling out all attributes. We try and do a modify + operation first, so this ensures that we don't leave old + attributes lying around. */ make_one_attr(&modlist,0,"pgpDisabled",NULL); make_one_attr(&modlist,0,"pgpKeyID",NULL); make_one_attr(&modlist,0,"pgpKeyType",NULL); @@ -530,8 +569,6 @@ send_key(int *eof) make_one_attr(&modlist,0,"pgpKeySize",NULL); make_one_attr(&modlist,0,"pgpKeyExpireTime",NULL); make_one_attr(&modlist,0,"pgpCertID",NULL); - /* Note the count of these deleted attributes. They're to be used - later. */ /* Assemble the INFO stuff into LDAP attributes */ @@ -587,7 +624,7 @@ send_key(int *eof) break; } else - build_attrs(&modlist,line); + build_attrs(&addlist,line); if(!end) { @@ -650,23 +687,28 @@ send_key(int *eof) goto fail; } - make_one_attr(&modlist,0,"objectClass","pgpKeyInfo"); - make_one_attr(&modlist,0,"pgpKey",key); + make_one_attr(&addlist,0,"objectClass","pgpKeyInfo"); + make_one_attr(&addlist,0,"pgpKey",key); + + /* Now append addlist onto modlist */ + if(!join_two_modlists(&modlist,addlist)) + { + fprintf(console,"gpgkeys: unable to merge LDAP modification lists\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } - /* If it's not there, we just turn around and send an add command - for the same key. Otherwise, the modify brings the server copy - into compliance with our copy. Note that unlike the LDAP - keyserver (and really, any other keyserver) this does NOT merge - signatures, but replaces the whole key. This should make some - people very happy. */ + /* Going on the assumption that modify operations are more frequent + than adds, we try a modify first. If it's not there, we just + turn around and send an add command for the same key. Otherwise, + the modify brings the server copy into compliance with our copy. + Note that unlike the LDAP keyserver (and really, any other + keyserver) this does NOT merge signatures, but replaces the whole + key. This should make some people very happy. */ err=ldap_modify_s(ldap,dn,modlist); if(err==LDAP_NO_SUCH_OBJECT) - { - /* This [11] is the deleted count from earlier */ - LDAPMod **addlist=&modlist[11]; - err=ldap_add_s(ldap,dn,addlist); - } + err=ldap_add_s(ldap,dn,addlist); if(err!=LDAP_SUCCESS) { @@ -687,6 +729,7 @@ send_key(int *eof) } free(modlist); + free(addlist); free(dn); if(ret!=0 && begin) |