/* $Id: sfskeyreg.C,v 1.34 2001/06/28 04:47:22 dm Exp $ */ /* * * Copyright (C) 1999 David Mazieres (dm@uun.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #include "sfskey.h" #include "srp.h" struct keyregstate { bool nokbdnoise; bool nosrp; u_int nbits; str keyname; str user; str host; sfskey k; sfssrp_parms srpparms; bool srpparms_set; ptr c; keyregstate () : nokbdnoise (false), nosrp (false), nbits (0), srpparms_set (false) {} void getclnt () { int fd = suidgetfd ("authserv"); if (fd < 0) fatal ("could not connect to authserv\n"); ptr x = axprt_stream::alloc (fd); c = aclnt::alloc (x, sfsauth_program_1); ref sfsc (aclnt::alloc (x, sfs_program_1)); host = myname (); if (!host) fatal ("cannot find my host name\n"); sfs_connectarg carg; sfs_connectres cres; sfs_initci (&carg, host, SFS_AUTHSERV); for (;;) { clnt_stat err = sfsc->scall (SFSPROC_CONNECT, &carg, &cres); if (!err) break; if (err != RPC_CANTDECODEARGS || !sfs_nextci (&carg)) fatal << "authserv: " << err << "\n"; } if (cres.status) fatal << "authserv connect: " << cres.status << "\n"; host = cres.reply->servinfo.host.hostname; } void getkey () { if (!user && !(user = myusername ())) fatal << "cannot find login name\n"; warnx << "Registering new user " << user << "@" << host << ".\n"; if (!keyname || (!isremote(keyname) && (access (keyname, 0) < 0 && errno == ENOENT))) { k.keyname = user << "@" << host; if (str err = keygen (&k, nbits, NULL, keyname, false, nokbdnoise)) fatal << err << "\n"; if (keyname) if (str err = keysave (keyname, &k)) warn << err << "\n"; } else if (str err = keyfetch (&k, keyname)) fatal << err << "\n"; } void setsrpparms () { sfsauth_srpparmsres res; if (nosrp || srpparms_set) return; if (k.srpparms) { srpparms = *k.srpparms; return; } if (clnt_stat err = c->scall (SFSAUTHPROC_SRP_GETPARAMS, NULL, &res)) fatal << "authserv: " << err << "\n"; if (res.status != SFSAUTH_OK) fatal << "could not get SRP parameters from server\n"; srpparms_set = true; srpparms.g = res.parms->g; srpparms.N = res.parms->N; } void sendrpc () { sfsauth_registerarg arg; arg.msg.type = SFS_AUTHREGISTER; arg.msg.username = user; arg.msg.pubkey = k.key->n; if (!nosrp) { arg.msg.srpinfo.alloc (); srp_client srp; str srpi = srp.create (srpparms.N, srpparms.g, k.pwd, host, k.cost); if (!srpi) fatal << "Failed to create SRP info\n"; arg.msg.srpinfo->info = srpi; arg.msg.srpinfo->privkey = export_rabin_encrypt_sec (*k.key, &srp.eksb); } for (int i = 0; i < 3; i++) { if (getuid ()) arg.msg.password = getpwd (" UNIX password: "); else arg.msg.password = ""; arg.sig = k.key->sign (xdr2str (arg.msg, true)); sfsauth_stat res; if (clnt_stat err = c->scall (SFSAUTHPROC_REGISTER, &arg, &res)) fatal << "authserv: " << err << "\n"; if (res == SFSAUTH_OK) return; if (res != SFSAUTH_BADPASSWORD) fatal << res << "\n"; warnx << res << "\n"; } fatal << "Too many tries\n"; } void doreg () { getclnt (); getkey (); setsrpparms (); sendrpc (); } }; void sfskey_reg (int argc, char **argv) { keyregstate kr; int ch; while ((ch = getopt (argc, argv, "KSs:b:c:u:")) != -1) switch (ch) { case 'K': kr.nokbdnoise = true; break; case 'S': kr.nosrp = true; break; case 's': { str sp = file2str (optarg); if (!sp) fatal ("%s: %m\n", optarg); else if (!import_srp_params (sp, &kr.srpparms.N, &kr.srpparms.g)) fatal ("%s: cannot parse file contents\n", optarg); else kr.srpparms_set = true; break; } case 'b': if (!convertint (optarg, &kr.nbits)) usage (); break; case 'c': if (!convertint (optarg, &kr.k.cost)) usage (); break; case 'u': kr.user = optarg; break; default: usage (); break; } if (optind + 1 < argc) usage (); if (optind + 1 == argc) kr.keyname = argv[optind]; else if (optind == argc) { if (!kr.user) { agent_mkdir (); kr.keyname = defkey (); } } else usage (); random_set_seedfile (RANDOM_SEED); kr.doreg (); exit (0); }