LDAP support w/ PGP 8.0 & iPlanet Directory Server

William Korb korb at qisc.com
Fri Jan 10 17:55:02 CET 2003


David,

Thanks for the prompt response.

> The current GnuPG LDAP plugin is based on a black box reverse
> engineering of the NAI (who owned PGP back then) LDAP keyserver.  I
> was able to figure out enough by sending queries from the openldap
> client tools to make a start, and then discovered
> http://www.openldap.org/lists/openldap-devel/199901/msg00022.html,
> which filled in the missing pieces.

Thanks for the excellent link. I was looking through the archives, but it 
was a less than fruitful search! ;-)

> Since there is no published standard for this, I'm not surprised that
> the pgp.com folks changed it to add new features.  It's nice that they
> support doing LDAP without the special keyserver now.  I believe
> that's a new thing.

And it works extremely well - on the PC client, you just say "Send key to 
keyserver" and it does all the heavy lifting. The hardest part of the 
entire process was figuring out the schema change and setting up the 
appropriate configuration stuff.

> > I already figured out why the searches were failing: the algorithm used
> > to find the pgpBaseKeySpaceDN in gpg simply looks for a cn=PGPServerInfo
> > entry in the base scope, whereas the PGP client queries the base scope
> > for all of the servers namingContexts then looks for a cn=PGPServerInfo
> > entry relative to each namingContext. I was able to create the code that
> > does that fairly easily.

> Interesting.  I don't think the LDAP keyserver supports this, so I
> suspect the client is trying it, and falling back if it doesn't
> succeed.

I deduced this from reading the README that came with the schema 
extension (the docs were, shall we say, less than excellent ;-). Yes, 
their keyserver as shipped includes the PGPServerInfo in the base scope, 
so that's why gpg can talk to it in the first place.

> > The object class violation seems to be a result of gpgkeys_ldap trying to
> > send a simple entry as pgpCertid=virtual,ou=pgpKeySpace,o=cray.com, but
> > this simple entry is missing some required attributes. I also don't
> > understand the significance of the "pgpCertid=virtual" keyid - the keys
> > that the PGP client inserts have the full 16 digit keys.

> The LDAP keyserver learns the pgpCertid by parsing the key itself, so
> the client doesn't have to tell it.  This is good, actually, as if the
> client was broken/compromised it could lie.  In the case of a
> non-keyserver LDAP server, of course, the client has to be trusted to
> send a valid pgpCertid.

> > So what I'm asking is this: is anyone actively working on getting the
> > LDAP plug-in to work in this type of environment?

> Not actively, but that doesn't mean "no".  I'd be interested in
> updating gpgkeys_ldap to work in your environment, but I don't want to
> raise any legal issues.  I am reluctant to look at the PGP 8 source
> for obvious reasons.

Well, we don't have access to any "source" code. I've pretty much 
reverse-engineered everything to get to where I am now.

The iPlanet Directory Server is extensible using their "plug-in" 
architecture, so I could probably duplicate what the PGP keyserver is 
doing with the pgpCertid=virtual thing by writing a plug-in, but since 
the PGP 8.0 client approach already assumes a trust relationship with the 
LDAP server, I'd rather do the same thing with gpg. Also, an iDS plug-in 
would also limit the utility of this change as it would then require that 
something comparable be added to any LDAP server that we'd want to use as 
a PGP key store.

I'll look at the resources called out in the URL you supplied above and 
see if there's enough information there to help me puzzle this out. Oh, 
did I mention we wanted to go live with this by 2/1? Yikes.

Thanks again for your assistance.

Bill

P.S. Here's an ed script that you can apply to the 1.2.1 gpgkeys_ldap.c 
to make pgpBaseKeySpaceDN discovery act like the PGP 8.0 client. This 
might help clear up what I'm talking about here a bit.



906a
   } /* end of non-namingContexts based search */

  ldap_msgfree(baseres);

.
846a
  if(err!=0 && err !=0x20) /* if not LDAP_SUCCESS or LDAP_NO_SUCH_OBJECT 
*/
    {
      fprintf(console,"gpgkeys: error retrieving LDAP server 
namingContexts: %s\n",
	      ldap_err2string(err));
      goto fail;
    }

/*
*	If we found one or more namingContexts, look for the PGPServerInfo
* object until we find one.
*/
  if(ldap_count_entries(ldap,baseres)>0)
    {
      if(verbose>1)
        {
          fprintf(console,"gpgkeys: found base namingContexts\n");
        }

      vals=ldap_get_values(ldap,baseres,"namingContexts");
      if(vals!=NULL)
        {
          int i;
          for ( i=0 ; vals[i] != NULL ; i++ )
            { /* begin for each namingContext */
              if(verbose>1)
                {
                  fprintf(console,"namingContexts: %s\n", vals[i]);
                }
/*
*	Look for PGPServerInfo in this namingContext:
*/
              err=ldap_search_s(ldap,vals[i],LDAP_SCOPE_SUBTREE,
                                "cn=PGPServerInfo",attrs,0,&res);
            
              if(err!=0 && err !=0x20) /* if not LDAP_SUCCESS or 
LDAP_NO_SUCH_OBJECT */
                {
                  fprintf(console,"gpgkeys: error retrieving LDAP server 
info: %s\n",
            	      ldap_err2string(err));
                  goto fail;
                }
              if (err==0x20) continue; /* Move on to the next 
namingContext */
              contextVals=ldap_get_values(ldap,res,"pgpbasekeyspacedn");
              if(contextVals!=NULL)
                {
                  basekeyspacedn=strdup(contextVals[0]);
                  ldap_value_free(contextVals);
                  if(basekeyspacedn==NULL)
                    {
                      fprintf(console,"gpgkeys: can't allocate string 
space "
                              "for LDAP base\n");
                      goto fail;
                    }
                  ldap_msgfree(res);
                  break;
                }

              ldap_msgfree(res);

            } /* end for each namingContext */
        } /* end if namingContexts found */
      ldap_value_free(vals);
    } /* end if one or more namingContexts */
  else	/* Beginning of non-namingContexts based search */
   {

/* Here's the original LDAP search code which doesn't use namingContexts 
*/

  /* Get the magic info record */
.
845c
/*
*	Look for all of the namingContexts attributes present in the BASE
* ldap scope. If we find one or more, loop through them looking for
* a PGPServerInfo object.
*/
  err=ldap_search_s(ldap,"",LDAP_SCOPE_BASE,
                    "(objectclass=*)",baseattrs,0,&baseres);
.
616a
  LDAPMessage *baseres;
.
615c
  char 
*attrs[]={"pgpbasekeyspacedn","basekeyspacedn","version","software",NULL
};
  char *baseattrs[]={"namingContexts",NULL};
.
613c
  char line[MAX_LINE],**vals,**contextVals;
.

---
William Korb, President & CTO          Phone:  715-382-5462
QISC, Inc.                             Fax:    715-382-5462
19945 82nd Ave., Suite 201             E-mail: korb at qisc.com
Chippewa Falls, WI 54729-5631          URL:    http://www.qisc.com/
"Tilting at Digital Windmills since 1995."







More information about the Gnupg-devel mailing list