[libvirt] Authentication with virConnectAuthPtr
Eduardo Otubo
otubo at linux.vnet.ibm.com
Thu May 7 05:30:54 UTC 2009
This sample of code helped me a lot!
Here is the phypOpen function I rewrited based on your code:
http://pastebin.com/f65912242 - I did a lot of tests with my HMC here
and everything seemed to be working fine. The prompt for the password
and the use of the public key.
I also did use the virRaiseError() to adjust all the error messages into
libvirt pattern. the modified function I made based on your sample code.
Thanks for the help.
[]'s
Em Ter, 2009-05-05 às 21:50 +0100, Daniel P. Berrange escreveu:
> On Tue, May 05, 2009 at 04:06:12PM -0300, Eduardo Otubo wrote:
> > Hello all,
> >
> > I'll start using virConnectAuthPtr to handle the authentication proccess
> > at the phyp driver I'm wrinting
> > <https://www.redhat.com/archives/libvir-list/2009-April/msg00493.html>
> > and I have some doubts in my mind:
> >
> > 1) What are the types of authentication that 'int *credtype' can hold?
> > And who fills it with the information I'll need?
>
> These are all defined in libvirt.h - we basically copied the SASL
> credential types
>
> VIR_CRED_USERNAME = 1, /* Identity to act as */
> VIR_CRED_AUTHNAME = 2, /* Identify to authorize as */
> VIR_CRED_LANGUAGE = 3, /* RFC 1766 languages, comma separated */
> VIR_CRED_CNONCE = 4, /* client supplies a nonce */
> VIR_CRED_PASSPHRASE = 5, /* Passphrase secret */
> VIR_CRED_ECHOPROMPT = 6, /* Challenge response */
> VIR_CRED_NOECHOPROMPT = 7, /* Challenge response */
> VIR_CRED_REALM = 8, /* Authentication realm */
> VIR_CRED_EXTERNAL = 9, /* Externally managed credential */
>
> The client application filles in the data in virConnectAuth struct,
> providing the function callback pointer, an opaque data blob (cddata)
> and the list of credential types it knows how to handle.
>
> > 2) Once known the credential type, I need to use the function pointer
> > 'virConnectAuthCallbackPtr cb' to get the information whatever it is,
> > right? I mean, it can be a password, a pubkey or anything else, right?
> > Is there a callback able to handle password or pubkeys?
>
> Yep, once your driver knows what credentials it needs to collect, it
> should check to see if the client has declared it supports the required
> credentials. If it does, then the driver should populate an array of
> virConnectCredential objects detailing what credentials needs to be
> collected. The callback is then invoked, and the client app will collect
> the credentials, putting the results in the 'result' / resultlen fields.
>
> When the callback returns, the driver can get the credentials fro mthe
> result/resultlen field - though it should check the callback return
> status to see if the client app had any errors.
>
> > 3) And finally I'll be able to use the 'void *cbdata' to manage the
> > authentication in my way. In my case, using libssh. In fact, in the end
> > of the process, I'll just need a password or a key to get things
> > working.
>
> The 'cbdata' field is something used by the client app. Both a password
> or private key passphrase would map to VIR_CRED_PASSPHRASE credential
> type. You'd just have a different prompt / challenge
>
> > There is no driver authenticatin agaist ssh channel, that's why I got so
> > confused with this topic.
> >
> > I don't know if my thoughts are pretty clear here. But I would like to
> > confirm the information 2 and 3, and check how 1 works. Could anyone
> > help me?
>
> Let me give you a close-to-working example that tries to illustrate
> the general idea from the driver point of view.
>
> First off, libvirt.so provides a generic callback that works for command
> line based apps, and knows how to collect credentials of type
>
> static int virConnectCredTypeDefault[] = {
> VIR_CRED_AUTHNAME,
> VIR_CRED_ECHOPROMPT,
> VIR_CRED_REALM,
> VIR_CRED_PASSPHRASE,
> VIR_CRED_NOECHOPROMPT,
> VIR_CRED_EXTERNAL,
> };
>
> static virConnectAuth virConnectAuthDefault = {
> virConnectCredTypeDefault,
> sizeof(virConnectCredTypeDefault)/sizeof(int),
> virConnectAuthCallbackDefault,
> NULL,
> };
>
>
> This is what virsh uses when connecting to libvirt
>
> ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault, 0)
>
>
>
> Now, in your Phyp driver, lets assume at some point in time libssh tells
> it wants a username+password.
>
> These will map to VIR_CRED_AUTHNAME and VIR_CRED_PASSPHRASE, so first
> step is to ensure the callback passed in by the client app supports
> these
>
> static virDrvOpenStatus phypOpen(virConnectPtr conn,
> virConnectAuthPtr auth,
> int flags) {
>
> .... start ssh conection ...
>
> if (need password) {
> int i;
> int hasPassphrase = 0
> int hasAuthname = 0;
> /* The creds we're about to ask the application for... */
> virConnectCredentials creds[] = {
> { VIR_CRED_AUTHNAME, "Enter username:", "Username", NULL, NULL, 0 },
> { VIR_CRED_PASSPHRASE, "Enter password:", "Password", NULL, NULL, 0 },
> };
>
> /* If no auth callback info was provided, must fail now */
> if (!auth || !auth->cb) {
> virPhypRaiseError(conn, VIR_ERR_AUTH_FAILED, "%s",
> _("no authentication callback provided"));
> return VIR_OPEN_FAILED;
> }
>
> /* Check if desired credentials are supported */
> for (i = 0 ; i < auth.ncredtype ; i++) {
> if (auth.credtype[i] == VIR_CRED_AUTHNAME)
> hasAuthName = 1;
> if (auth.credtype[i] == VIR_CRED_PASSPHRASE)
> hasPassphrase = 1;
> }
> if (!hasPassphrase || !hasAuthname) {
> virPhypRaiseError(conn, VIR_ERR_AUTH_FAILED, "%s",
> _("required credentials are not supported"));
> return VIR_OPEN_FAILED;
> }
>
>
> /* Credential supported, to try to get them from user */
> int res = (auth->cb)(creds, ARRAY_CARDINALITY(creds), auth->cbdata);
>
> if (res < 0) {
> virPhypRaiseError(conn, VIR_ERR_AUTH_FAILED, "%s",
> _("unable to fetch credentials"));
> return VIR_OPEN_FAILED;
> }
>
> char *username = creds[0]->result;
> char *password = creds[1]->result;
> .... give these back to libssh now ....
> }
>
>
> This example code is quite inflexible & hardcoded to the specifics of
> getting a username + password. Depending on libssh's API you may want
> or need todo things slightly differently. For example, you probably
> won't need to actually prompt for username, since I imagine you're
> getting that from the connection URI directly.
>
> You may have to try several credentials in turn, requiring multiple
> invocations of the callback. For example, first time you may prompt
> for a passphrase for a SSH private key. If private key auth fails,
> you may then continue onto password based auth, and need to prompt
> for login password. So in that cae you'd be invoking the callback
> twice asking for different types of data each time.
>
> Also, don't assume that the 'result' field is NULL terminated, or
> that 'result' is even non-NULL - sanity check this data you get
> back from the client app before using it.
>
> Regards,
> Daniel
--
Eduardo Otubo
Software Engineer
Linux Technology Center
IBM Systems & Technology Group
Mobile: +55 19 8135 0885
otubo at linux.vnet.ibm.com
More information about the libvir-list
mailing list