Example #1
0
/*
 * Open the log file. Takes care of detecting an already-existing
 * file and asking the user whether they want to append, overwrite
 * or cancel logging.
 */
void logfopen(void *handle)
{
    struct LogContext *ctx = (struct LogContext *)handle;
    struct tm tm;
    int mode;

    /* Prevent repeat calls */
    if (ctx->state != L_CLOSED)
        return;

    if (!ctx->cfg.logtype)
        return;

    tm = ltime();

    /* substitute special codes in file name */
    xlatlognam(&ctx->currlogfilename, ctx->cfg.logfilename,&ctx->cfg, &tm);

    ctx->lgfp = f_open(&ctx->currlogfilename, "r", FALSE);  /* file already present? */
    if (ctx->lgfp) {
        fclose(ctx->lgfp);
        if (ctx->cfg.logxfovr != LGXF_ASK) {
            mode = ((ctx->cfg.logxfovr == LGXF_OVR) ? 2 : 1);
        } else
            mode = askappend(ctx->frontend, ctx->currlogfilename,
                             logfopen_callback, ctx);
    } else
        mode = 2;		       /* create == overwrite */

    if (mode < 0)
        ctx->state = L_OPENING;
    else
        logfopen_callback(ctx, mode);  /* open the file */
}
/**
 * Add a new client
 */
void
add_radiusAccClientExtTable(dm_id id, struct dm_value_table *client)
{
	radiusAccClientExtTable_context *row;

	ENTER();

	if (!my_handler) {
		EXIT();
		return;
	}

	row = malloc(sizeof(radiusAccClientExtTable_context));
	if (!row) {
		EXIT();
		return;
	}

	row->radiusAccServerCounterDiscontinuity = ltime();
	row->index.len = 1;
	row->index.oids = &row->oid[0];
	row->oid[0] = id;
	row->radiusAccClientExtIndex = id;
	row->client = client;
	debug("inserting row: %d (%p), client: %p", id, row, client);
	CONTAINER_INSERT(cb.container, row);

	EXIT();
}
Example #3
0
void add_log( const char* function, const char* file, char_data* ch,
  const char* string )
{
  char      tmp  [ MAX_INPUT_LENGTH+20 ];
  FILE*      fp;

  if( ( fp = fopen( file, "a" ) ) == NULL ) {
    bug( "%s: Could not open file.", function );
    return;
    }

  sprintf( tmp, "[%s] %s", ltime( current_time )+4, string );

  tmp[15] = toupper( tmp[15] );

  if( strlen( tmp ) > 60 ) {
    sprintf( tmp+60, "...  %s\r\n", ch->real_name( ) );
    fprintf( fp, tmp );
    }
  else
    fprintf( fp, "%-65s%s\r\n", tmp, ch->real_name( ) );
   
  fclose( fp );

  return;
}
Example #4
0
static void logfopen_callback(void *handle, int mode)
{
    struct LogContext *ctx = (struct LogContext *)handle;
    char buf[256], *event;
    struct tm tm;
    const char *fmode;

    if (mode == 0) {
        ctx->state = L_ERROR;	       /* disable logging */
    } else {
        fmode = (mode == 1 ? "ab" : "wb");
        ctx->lgfp = f_open(&ctx->currlogfilename, fmode, FALSE);
        if (ctx->lgfp)
            ctx->state = L_OPEN;
        else
            ctx->state = L_ERROR;
    }

    if (ctx->state == L_OPEN) {
        /* Write header line into log file. */
        tm = ltime();
        strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm);
        logprintf(ctx, "=~=~=~=~=~=~=~=~=~=~=~= PuTTY log %s"
                  " =~=~=~=~=~=~=~=~=~=~=~=\r\n", buf);
    }

    event = dupprintf("%s session log (%s mode) to file: %s",
                      ctx->state == L_ERROR ?
                      (mode == 0 ? "Disabled writing" : "Error writing") :
                      (mode == 1 ? "Appending" : "Writing new"),
                      (ctx->cfg.logtype == LGTYP_ASCII ? "ASCII" :
                       ctx->cfg.logtype == LGTYP_DEBUG ? "raw" :
                       ctx->cfg.logtype == LGTYP_PACKETS ? "SSH packets" :
                       ctx->cfg.logtype == LGTYP_SSHRAW ? "SSH raw data" :
                       "unknown"),
                      filename_to_str(&ctx->currlogfilename));
    logevent(ctx->frontend, event);
    sfree(event);

    /*
     * Having either succeeded or failed in opening the log file,
     * we should write any queued data out.
     */
    assert(ctx->state != L_OPENING);   /* make _sure_ it won't be requeued */
    while (bufchain_size(&ctx->queue)) {
        void *data;
        int len;
        bufchain_prefix(&ctx->queue, &data, &len);
        logwrite(ctx, data, len);
        bufchain_consume(&ctx->queue, len);
    }
}
Example #5
0
void immortal_log( char_data* ch, char* cmd, char* arg )
{
  char    file  [ ONE_LINE ];
  FILE*     fp;
  
  sprintf( file, "%s%s", IMMORTAL_LOG_DIR, ch->real_name( ) );

  if( ( fp = fopen( file, "a" ) ) != NULL ) {
    fprintf( fp, "[%s] %s %s\n",
      ltime( current_time )+4, cmd, arg );
    fclose( fp );
    }

  return;
}
Example #6
0
/*
 * Open the log file. Takes care of detecting an already-existing
 * file and asking the user whether they want to append, overwrite
 * or cancel logging.
 */
void logfopen(void *handle)
{
    struct LogContext *ctx = (struct LogContext *)handle;
    struct tm tm;
    FILE *fp;
    int mode;

    /* Prevent repeat calls */
    if (ctx->state != L_CLOSED)
	return;

    if (!ctx->logtype)
	return;

    tm = ltime();

    /* substitute special codes in file name */
    if (ctx->currlogfilename)
        filename_free(ctx->currlogfilename);
    ctx->currlogfilename = 
        xlatlognam(conf_get_filename(ctx->conf, CONF_logfilename),
                   conf_get_str(ctx->conf, CONF_host),
                   conf_get_int(ctx->conf, CONF_port), &tm);
#ifdef PERSOPORT
	test_dir( /*&*/ctx->currlogfilename ) ;
#endif

    fp = f_open(ctx->currlogfilename, "r", FALSE);  /* file already present? */
    if (fp) {
	int logxfovr = conf_get_int(ctx->conf, CONF_logxfovr);
	fclose(fp);
	if (logxfovr != LGXF_ASK) {
	    mode = ((logxfovr == LGXF_OVR) ? 2 : 1);
	} else
	    mode = askappend(ctx->frontend, ctx->currlogfilename,
			     logfopen_callback, ctx);
    } else
	mode = 2;		       /* create == overwrite */

    if (mode < 0)
	ctx->state = L_OPENING;
    else
	logfopen_callback(ctx, mode);  /* open the file */
}
Example #7
0
void player_log( char_data* ch, const char* string )
{
  char    file  [ ONE_LINE ];
  FILE*     fp;

  if( ch->pcdata == NULL
    || string == empty_string )
    return;

  sprintf( file, "%s%s", PLAYER_LOG_DIR, ch->real_name( ) );

  if( ( fp = open_file( file, "a" ) ) == NULL )
    return;

  fprintf( fp, "[%s] %s\r\n", ltime( current_time )+4, string );
  fclose( fp );

  return;
}
Example #8
0
void logLine( enum eLogLevel level, char const * fmt, ... ) {
    logginginfo_t* lLoggingTls;
    char const* lShortFile;
    char lBuf[ 0x1000 ];
    va_list lArguments;
    if ( level < gMinLoggingLevel ) return;
    lLoggingTls = ( logginginfo_t* )loggingTlsGet();
    lShortFile = strrchr( lLoggingTls->file, '/' );
    lShortFile = lShortFile ? lShortFile + 1 : lLoggingTls->file;
    lBuf[ 0 ] = 0;
    if ( fmt ) {
        va_start( lArguments, fmt );
        #ifdef WIN32
            _vsnprintf( lBuf, sizeof(lBuf), fmt, lArguments );
        #else
            vsnprintf( lBuf, sizeof(lBuf), fmt, lArguments );
        #endif
        va_end(lArguments);
    }
    //fprintf( stderr, "%s %s: %s\n", gLoggingLevels[level], ltime(), lBuf );
    //fprintf( stderr, "%s %s %s[%d]: %s\n", gLoggingLevels[level], ltime(), lLoggingTls->file, lLoggingTls->line, lBuf );
    fprintf( stderr, "%s %s %s[%d]: %s\n", gLoggingLevels[level], ltime(), lShortFile, lLoggingTls->line, lBuf );
}
Example #9
0
int main(int argc, char **argv)
{
    char *infile = NULL;
    Filename infilename;
    enum { NOKEYGEN, RSA1, RSA2, DSA } keytype = NOKEYGEN;    
    char *outfile = NULL, *outfiletmp = NULL;
    Filename outfilename;
    enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH, SSHCOM } outtype = PRIVATE;
    int bits = 2048;
    char *comment = NULL, *origcomment = NULL;
    int change_passphrase = FALSE;
    int errs = FALSE, nogo = FALSE;
    int intype = SSH_KEYTYPE_UNOPENABLE;
    int sshver = 0;
    struct ssh2_userkey *ssh2key = NULL;
    struct RSAKey *ssh1key = NULL;
    unsigned char *ssh2blob = NULL;
    char *ssh2alg = NULL;
    const struct ssh_signkey *ssh2algf = NULL;
    int ssh2bloblen;
    char *passphrase = NULL;
    int load_encrypted;
    progfn_t progressfn = is_interactive() ? progress_update : no_progress;

    /* ------------------------------------------------------------------
     * Parse the command line to figure out what we've been asked to do.
     */

    /*
     * If run with no arguments at all, print the usage message and
     * return success.
     */
    if (argc <= 1) {
	usage(TRUE);
	return 0;
    }

    /*
     * Parse command line arguments.
     */
    while (--argc) {
	char *p = *++argv;
	if (*p == '-') {
	    /*
	     * An option.
	     */
	    while (p && *++p) {
		char c = *p;
		switch (c) {
		  case '-':
		    /*
		     * Long option.
		     */
		    {
			char *opt, *val;
			opt = p++;     /* opt will have _one_ leading - */
			while (*p && *p != '=')
			    p++;	       /* find end of option */
			if (*p == '=') {
			    *p++ = '\0';
			    val = p;
			} else
                            val = NULL;

			if (!strcmp(opt, "-help")) {
                            if (val) {
                                errs = TRUE;
                                fprintf(stderr, "puttygen: option `-%s'"
                                        " expects no argument\n", opt);
                            } else {
                                help();
                                nogo = TRUE;
                            }
			} else if (!strcmp(opt, "-version")) {
                            if (val) {
                                errs = TRUE;
                                fprintf(stderr, "puttygen: option `-%s'"
                                        " expects no argument\n", opt);
                            } else {
                                showversion();
                                nogo = TRUE;
                            }
			} else if (!strcmp(opt, "-pgpfp")) {
                            if (val) {
                                errs = TRUE;
                                fprintf(stderr, "puttygen: option `-%s'"
                                        " expects no argument\n", opt);
                            } else {
                                /* support --pgpfp for consistency */
                                pgp_fingerprints();
                                nogo = TRUE;
                            }
                        }
			/*
			 * For long options requiring an argument, add
			 * code along the lines of
			 * 
			 * else if (!strcmp(opt, "-output")) {
			 *     if (!val) {
			 *         errs = TRUE;
                         *         fprintf(stderr, "puttygen: option `-%s'"
                         *                 " expects an argument\n", opt);
			 *     } else
			 *         ofile = val;
			 * }
			 */
			else {
			    errs = TRUE;
			    fprintf(stderr,
				    "puttygen: no such option `-%s'\n", opt);
			}
		    }
		    p = NULL;
		    break;
		  case 'h':
		  case 'V':
		  case 'P':
		  case 'l':
		  case 'L':
		  case 'p':
		  case 'q':
		    /*
		     * Option requiring no parameter.
		     */
		    switch (c) {
		      case 'h':
			help();
			nogo = TRUE;
			break;
		      case 'V':
			showversion();
			nogo = TRUE;
			break;
		      case 'P':
			change_passphrase = TRUE;
			break;
		      case 'l':
			outtype = FP;
			break;
		      case 'L':
			outtype = PUBLICO;
			break;
		      case 'p':
			outtype = PUBLIC;
			break;
		      case 'q':
			progressfn = no_progress;
			break;
		    }
		    break;
		  case 't':
		  case 'b':
		  case 'C':
		  case 'O':
		  case 'o':
		    /*
		     * Option requiring parameter.
		     */
		    p++;
		    if (!*p && argc > 1)
			--argc, p = *++argv;
		    else if (!*p) {
			fprintf(stderr, "puttygen: option `-%c' expects a"
				" parameter\n", c);
			errs = TRUE;
		    }
		    /*
		     * Now c is the option and p is the parameter.
		     */
		    switch (c) {
		      case 't':
			if (!strcmp(p, "rsa") || !strcmp(p, "rsa2"))
			    keytype = RSA2, sshver = 2;
			else if (!strcmp(p, "rsa1"))
			    keytype = RSA1, sshver = 1;
			else if (!strcmp(p, "dsa") || !strcmp(p, "dss"))
			    keytype = DSA, sshver = 2;
			else {
			    fprintf(stderr,
				    "puttygen: unknown key type `%s'\n", p);
			    errs = TRUE;
			}
                        break;
		      case 'b':
			bits = atoi(p);
                        break;
		      case 'C':
			comment = p;
                        break;
		      case 'O':
			if (!strcmp(p, "public"))
			    outtype = PUBLIC;
			else if (!strcmp(p, "public-openssh"))
			    outtype = PUBLICO;
			else if (!strcmp(p, "private"))
			    outtype = PRIVATE;
			else if (!strcmp(p, "fingerprint"))
			    outtype = FP;
			else if (!strcmp(p, "private-openssh"))
			    outtype = OPENSSH, sshver = 2;
			else if (!strcmp(p, "private-sshcom"))
			    outtype = SSHCOM, sshver = 2;
			else {
			    fprintf(stderr,
				    "puttygen: unknown output type `%s'\n", p);
			    errs = TRUE;
			}
                        break;
		      case 'o':
			outfile = p;
                        break;
		    }
		    p = NULL;	       /* prevent continued processing */
		    break;
		  default:
		    /*
		     * Unrecognised option.
		     */
		    errs = TRUE;
		    fprintf(stderr, "puttygen: no such option `-%c'\n", c);
		    break;
		}
	    }
	} else {
	    /*
	     * A non-option argument.
	     */
	    if (!infile)
		infile = p;
	    else {
		errs = TRUE;
		fprintf(stderr, "puttygen: cannot handle more than one"
			" input file\n");
	    }
	}
    }

    if (errs)
	return 1;

    if (nogo)
	return 0;

    /*
     * If run with at least one argument _but_ not the required
     * ones, print the usage message and return failure.
     */
    if (!infile && keytype == NOKEYGEN) {
	usage(TRUE);
	return 1;
    }

    /* ------------------------------------------------------------------
     * Figure out further details of exactly what we're going to do.
     */

    /*
     * Bomb out if we've been asked to both load and generate a
     * key.
     */
    if (keytype != NOKEYGEN && infile) {
	fprintf(stderr, "puttygen: cannot both load and generate a key\n");
	return 1;
    }

    /* 
     * We must save the private part when generating a new key.
     */
    if (keytype != NOKEYGEN &&
	(outtype != PRIVATE && outtype != OPENSSH && outtype != SSHCOM)) {
	fprintf(stderr, "puttygen: this would generate a new key but "
		"discard the private part\n");
	return 1;
    }

    /*
     * Analyse the type of the input file, in case this affects our
     * course of action.
     */
    if (infile) {
	infilename = filename_from_str(infile);

	intype = key_type(&infilename);

	switch (intype) {
	    /*
	     * It would be nice here to be able to load _public_
	     * key files, in any of a number of forms, and (a)
	     * convert them to other public key types, (b) print
	     * out their fingerprints. Or, I suppose, for real
	     * orthogonality, (c) change their comment!
	     * 
	     * In fact this opens some interesting possibilities.
	     * Suppose ssh2_userkey_loadpub() were able to load
	     * public key files as well as extracting the public
	     * key from private ones. And suppose I did the thing
	     * I've been wanting to do, where specifying a
	     * particular private key file for authentication
	     * causes any _other_ key in the agent to be discarded.
	     * Then, if you had an agent forwarded to the machine
	     * you were running Unix PuTTY or Plink on, and you
	     * needed to specify which of the keys in the agent it
	     * should use, you could do that by supplying a
	     * _public_ key file, thus not needing to trust even
	     * your encrypted private key file to the network. Ooh!
	     */

	  case SSH_KEYTYPE_UNOPENABLE:
	  case SSH_KEYTYPE_UNKNOWN:
	    fprintf(stderr, "puttygen: unable to load file `%s': %s\n",
		    infile, key_type_to_str(intype));
	    return 1;

	  case SSH_KEYTYPE_SSH1:
	    if (sshver == 2) {
		fprintf(stderr, "puttygen: conversion from SSH-1 to SSH-2 keys"
			" not supported\n");
		return 1;
	    }
	    sshver = 1;
	    break;

	  case SSH_KEYTYPE_SSH2:
	  case SSH_KEYTYPE_OPENSSH:
	  case SSH_KEYTYPE_SSHCOM:
	    if (sshver == 1) {
		fprintf(stderr, "puttygen: conversion from SSH-2 to SSH-1 keys"
			" not supported\n");
		return 1;
	    }
	    sshver = 2;
	    break;
	}
    }

    /*
     * Determine the default output file, if none is provided.
     * 
     * This will usually be equal to stdout, except that if the
     * input and output file formats are the same then the default
     * output is to overwrite the input.
     * 
     * Also in this code, we bomb out if the input and output file
     * formats are the same and no other action is performed.
     */
    if ((intype == SSH_KEYTYPE_SSH1 && outtype == PRIVATE) ||
	(intype == SSH_KEYTYPE_SSH2 && outtype == PRIVATE) ||
	(intype == SSH_KEYTYPE_OPENSSH && outtype == OPENSSH) ||
	(intype == SSH_KEYTYPE_SSHCOM && outtype == SSHCOM)) {
	if (!outfile) {
	    outfile = infile;
	    outfiletmp = dupcat(outfile, ".tmp", NULL);
	}

	if (!change_passphrase && !comment) {
	    fprintf(stderr, "puttygen: this command would perform no useful"
		    " action\n");
	    return 1;
	}
    } else {
	if (!outfile) {
	    /*
	     * Bomb out rather than automatically choosing to write
	     * a private key file to stdout.
	     */
	    if (outtype==PRIVATE || outtype==OPENSSH || outtype==SSHCOM) {
		fprintf(stderr, "puttygen: need to specify an output file\n");
		return 1;
	    }
	}
    }

    /*
     * Figure out whether we need to load the encrypted part of the
     * key. This will be the case if either (a) we need to write
     * out a private key format, or (b) the entire input key file
     * is encrypted.
     */
    if (outtype == PRIVATE || outtype == OPENSSH || outtype == SSHCOM ||
	intype == SSH_KEYTYPE_OPENSSH || intype == SSH_KEYTYPE_SSHCOM)
	load_encrypted = TRUE;
    else
	load_encrypted = FALSE;

    /* ------------------------------------------------------------------
     * Now we're ready to actually do some stuff.
     */

    /*
     * Either load or generate a key.
     */
    if (keytype != NOKEYGEN) {
	char *entropy;
	char default_comment[80];
	struct tm tm;
	struct progress prog;

	prog.phase = -1;
	prog.current = -1;

	tm = ltime();
	if (keytype == DSA)
	    strftime(default_comment, 30, "dsa-key-%Y%m%d", &tm);
	else
	    strftime(default_comment, 30, "rsa-key-%Y%m%d", &tm);

	random_ref();
	entropy = get_random_data(bits / 8);
	if (!entropy) {
	    fprintf(stderr, "puttygen: failed to collect entropy, "
		    "could not generate key\n");
	    return 1;
	}
	random_add_heavynoise(entropy, bits / 8);
	memset(entropy, 0, bits/8);
	sfree(entropy);

	if (keytype == DSA) {
	    struct dss_key *dsskey = snew(struct dss_key);
	    dsa_generate(dsskey, bits, progressfn, &prog);
	    ssh2key = snew(struct ssh2_userkey);
	    ssh2key->data = dsskey;
	    ssh2key->alg = &ssh_dss;
	    ssh1key = NULL;
	} else {
Example #10
0
void display_last( pfile_data* pfile, char_data* ch )
{
  page( ch, "%-15s %s  %s\n\r", pfile->name,
    ltime( pfile->last_on ),
    is_demigod( ch ) ? pfile->last_host : "" );
}
Example #11
0
/*
 * Log an SSH packet.
 * If n_blanks != 0, blank or omit some parts.
 * Set of blanking areas must be in increasing order.
 */
void log_packet(void *handle, int direction, int type,
		const char *texttype, const void *data, int len,
		int n_blanks, const struct logblank_t *blanks,
		const unsigned long *seq,
                unsigned downstream_id, const char *additional_log_text)
{
    struct LogContext *ctx = (struct LogContext *)handle;
    char dumpdata[80], smalldata[5];
    int p = 0, b = 0, omitted = 0;
    int output_pos = 0; /* NZ if pending output in dumpdata */

    if (!(ctx->logtype == LGTYP_SSHRAW ||
          (ctx->logtype == LGTYP_PACKETS && texttype)))
	return;

    /* Packet header. */
    if (texttype) {
        logprintf(ctx, "%s packet ",
                  direction == PKT_INCOMING ? "Incoming" : "Outgoing");

	if (seq)
	    logprintf(ctx, "#0x%lx, ", *seq);

        logprintf(ctx, "type %d / 0x%02x (%s)", type, type, texttype);

        if (downstream_id) {
	    logprintf(ctx, " on behalf of downstream #%u", downstream_id);
            if (additional_log_text)
                logprintf(ctx, " (%s)", additional_log_text);
        }

        logprintf(ctx, "\r\n");
    } else {
        /*
         * Raw data is logged with a timestamp, so that it's possible
         * to determine whether a mysterious delay occurred at the
         * client or server end. (Timestamping the raw data avoids
         * cluttering the normal case of only logging decrypted SSH
         * messages, and also adds conceptual rigour in the case where
         * an SSH message arrives in several pieces.)
         */
        char buf[256];
        struct tm tm;
	tm = ltime();
	strftime(buf, 24, "%Y-%m-%d %H:%M:%S", &tm);
        logprintf(ctx, "%s raw data at %s\r\n",
                  direction == PKT_INCOMING ? "Incoming" : "Outgoing",
                  buf);
    }

    /*
     * Output a hex/ASCII dump of the packet body, blanking/omitting
     * parts as specified.
     */
    while (p < len) {
	int blktype;

	/* Move to a current entry in the blanking array. */
	while ((b < n_blanks) &&
	       (p >= blanks[b].offset + blanks[b].len))
	    b++;
	/* Work out what type of blanking to apply to
	 * this byte. */
	blktype = PKTLOG_EMIT; /* default */
	if ((b < n_blanks) &&
	    (p >= blanks[b].offset) &&
	    (p < blanks[b].offset + blanks[b].len))
	    blktype = blanks[b].type;

	/* If we're about to stop omitting, it's time to say how
	 * much we omitted. */
	if ((blktype != PKTLOG_OMIT) && omitted) {
	    logprintf(ctx, "  (%d byte%s omitted)\r\n",
		      omitted, (omitted==1?"":"s"));
	    omitted = 0;
	}

	/* (Re-)initialise dumpdata as necessary
	 * (start of row, or if we've just stopped omitting) */
	if (!output_pos && !omitted)
	    sprintf(dumpdata, "  %08x%*s\r\n", p-(p%16), 1+3*16+2+16, "");

	/* Deal with the current byte. */
	if (blktype == PKTLOG_OMIT) {
	    omitted++;
	} else {
	    int c;
	    if (blktype == PKTLOG_BLANK) {
		c = 'X';
		sprintf(smalldata, "XX");
	    } else {  /* PKTLOG_EMIT */
		c = ((unsigned char *)data)[p];
		sprintf(smalldata, "%02x", c);
	    }
	    dumpdata[10+2+3*(p%16)] = smalldata[0];
	    dumpdata[10+2+3*(p%16)+1] = smalldata[1];
	    dumpdata[10+1+3*16+2+(p%16)] = (isprint(c) ? c : '.');
	    output_pos = (p%16) + 1;
	}

	p++;

	/* Flush row if necessary */
	if (((p % 16) == 0) || (p == len) || omitted) {
	    if (output_pos) {
		strcpy(dumpdata + 10+1+3*16+2+output_pos, "\r\n");
		logwrite(ctx, dumpdata, strlen(dumpdata));
		output_pos = 0;
	    }
	}

    }

    /* Tidy up */
    if (omitted)
	logprintf(ctx, "  (%d byte%s omitted)\r\n",
		  omitted, (omitted==1?"":"s"));
    logflush(ctx);
}
/************************************************************
 * radiusAccClientExtTable_get_value
 *
 * This routine is called for get requests to copy the data
 * from the context to the varbind for the request. If the
 * context has been properly maintained, you don't need to
 * change in code in this fuction.
 */
int
radiusAccClientExtTable_get_value(netsnmp_request_info *request,
                                  netsnmp_index * item,
                                  netsnmp_table_request_info *table_info)
{
	netsnmp_variable_list *var = request->requestvb;
	radiusAccClientExtTable_context *ctx =
		(radiusAccClientExtTable_context *)item;
	struct dm_value_table *stats;

	ENTER();

	if (!ctx->client) {
		snmp_log(LOG_ERR, "invalid client in "
			 "radiusAccClientExtTable_get_value\n");
		EXIT();
		return SNMP_ERR_GENERR;
	}

	/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Stats */
	stats = dm_get_table_by_id(ctx->client, dm__IGD_SCG_RS_Acct_Clnt_i_Stats);

	switch (table_info->colnum) {
	case COLUMN_RADIUSACCCLIENTINETADDRESSTYPE:
		/** InetAddressType = ASN_INTEGER */
		snmp_set_var_typed_integer(var, ASN_INTEGER, INETADDRESSTYPE_IPV4);
		break;
	    
	case COLUMN_RADIUSACCCLIENTINETADDRESS: {
		char hname[NI_MAXHOST];
		struct in_addr host;
	    
		/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Prefix */
		host = dm_get_ipv4_by_id(ctx->client, dm__IGD_SCG_RS_Acct_Clnt_i_Prefix);
		inet_ntop(AF_INET, &host, hname, sizeof(hname));
	    
		/** InetAddress = ASN_OCTET_STR */
		snmp_set_var_typed_value(var, ASN_OCTET_STR, (unsigned char *)hname, strlen(hname));
		break;
	}
	    
	case COLUMN_RADIUSACCCLIENTEXTID: {
		unsigned char *id;

		/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Description */
		id = dm_get_string_by_id(ctx->client, dm__IGD_SCG_RS_Acct_Clnt_i_Description);
		if (!id || !*id)
			id = "";

		/** SnmpAdminString = ASN_OCTET_STR */
		snmp_set_var_typed_value(var, ASN_OCTET_STR, id, strlen(id));
		break;
	}

	case COLUMN_RADIUSACCSERVEXTPACKETSDROPPED:
		/** COUNTER = ASN_COUNTER */
		/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Stats.PacketsDropped */
		snmp_set_var_typed_integer(var, ASN_COUNTER, dm_get_uint_by_id(stats, dm__IGD_SCG_RS_Acct_Clnt_i_Stats_PacketsDropped));
		break;
	    
	case COLUMN_RADIUSACCSERVEXTREQUESTS:
		/** COUNTER = ASN_COUNTER */
		/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Stats.Requests */
		snmp_set_var_typed_integer(var, ASN_COUNTER, dm_get_uint_by_id(stats, dm__IGD_SCG_RS_Acct_Clnt_i_Stats_Requests));
		break;
	    
	case COLUMN_RADIUSACCSERVEXTDUPREQUESTS:
		/** COUNTER = ASN_COUNTER */
		/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Stats.DupRequests */
		snmp_set_var_typed_integer(var, ASN_COUNTER, dm_get_uint_by_id(stats, dm__IGD_SCG_RS_Acct_Clnt_i_Stats_DupRequests));
		break;
	    
	case COLUMN_RADIUSACCSERVEXTRESPONSES:
		/** COUNTER = ASN_COUNTER */
		/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Stats.Responses */
		snmp_set_var_typed_integer(var, ASN_COUNTER, dm_get_uint_by_id(stats, dm__IGD_SCG_RS_Acct_Clnt_i_Stats_Responses));
		break;
	    
	case COLUMN_RADIUSACCSERVEXTBADAUTHENTICATORS:
		/** COUNTER = ASN_COUNTER */
		/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Stats.BadAuthenticators */
		snmp_set_var_typed_integer(var, ASN_COUNTER, dm_get_uint_by_id(stats, dm__IGD_SCG_RS_Acct_Clnt_i_Stats_BadAuthenticators));
		break;
	    
	case COLUMN_RADIUSACCSERVEXTMALFORMEDREQUESTS:
		/** COUNTER = ASN_COUNTER */
		/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Stats.MalformedRequests */
		snmp_set_var_typed_integer(var, ASN_COUNTER, dm_get_uint_by_id(stats, dm__IGD_SCG_RS_Acct_Clnt_i_Stats_MalformedRequests));
		break;
	    
	case COLUMN_RADIUSACCSERVEXTNORECORDS:
		/** COUNTER = ASN_COUNTER */
		/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Stats.NoRecords */
		snmp_set_var_typed_integer(var, ASN_COUNTER, dm_get_uint_by_id(stats, dm__IGD_SCG_RS_Acct_Clnt_i_Stats_NoRecords));
		break;
	    
	case COLUMN_RADIUSACCSERVEXTUNKNOWNTYPES:
		/** COUNTER = ASN_COUNTER */
		/** VAR: InternetGatewayDevice.X_TPLINO_NET_SessionControl.RadiusServer.Accounting.Client.{i}.Stats.UnknownTypes */
		snmp_set_var_typed_integer(var, ASN_COUNTER, dm_get_uint_by_id(stats, dm__IGD_SCG_RS_Acct_Clnt_i_Stats_UnknownTypes));
		break;
	    
	case COLUMN_RADIUSACCSERVERCOUNTERDISCONTINUITY:
		/** TICKS = ASN_TIMETICKS */
		snmp_set_var_typed_integer(var, ASN_TIMETICKS, 
					   (ltime() - ctx->radiusAccServerCounterDiscontinuity) / 10);
		break;
	    
	default:/** We shouldn't get here */
		snmp_log(LOG_ERR, "unknown column in "
			 "radiusAccClientExtTable_get_value\n");
		EXIT();
		return SNMP_ERR_GENERR;
	}

	EXIT();
	return SNMP_ERR_NOERROR;
}
Example #13
0
static void logfopen_callback(void *handle, int mode)
{
    struct LogContext *ctx = (struct LogContext *)handle;
    char buf[256], *event;
    struct tm tm;
    const char *fmode;
    int shout = FALSE;

    if (mode == 0) {
	ctx->state = L_ERROR;	       /* disable logging */
    } else {
	fmode = (mode == 1 ? "ab" : "wb");
	ctx->lgfp = f_open(ctx->currlogfilename, fmode, FALSE);
	if (ctx->lgfp) {
	    ctx->state = L_OPEN;
        } else {
	    ctx->state = L_ERROR;
            shout = TRUE;
        }
    }

    if (ctx->state == L_OPEN) {
	/* Write header line into log file. */
	tm = ltime();
	strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm);
	logprintf(ctx, "=~=~=~=~=~=~=~=~=~=~=~= PuTTY log %s"
		  " =~=~=~=~=~=~=~=~=~=~=~=\r\n", buf);
    }

    event = dupprintf(MPEXT_BOM "%s session log (%s mode) to file: %s",
		      ctx->state == L_ERROR ?
		      (mode == 0 ? "Disabled writing" : "Error writing") :
		      (mode == 1 ? "Appending" : "Writing new"),
		      (ctx->logtype == LGTYP_ASCII ? "ASCII" :
		       ctx->logtype == LGTYP_DEBUG ? "raw" :
		       ctx->logtype == LGTYP_PACKETS ? "SSH packets" :
		       ctx->logtype == LGTYP_SSHRAW ? "SSH raw data" :
		       "unknown"),
		      filename_to_str(ctx->currlogfilename));
    logevent(ctx->frontend, event);
    if (shout) {
        /*
         * If we failed to open the log file due to filesystem error
         * (as opposed to user action such as clicking Cancel in the
         * askappend box), we should log it more prominently. We do
         * this by sending it to the same place that stderr output
         * from the main session goes (so, either a console tool's
         * actual stderr, or a terminal window).
         *
         * Of course this is one case in which that policy won't cause
         * it to turn up embarrassingly in a log file of real server
         * output, because the whole point is that we haven't managed
         * to open any such log file :-)
         */
        from_backend(ctx->frontend, 1, event, strlen(event));
        from_backend(ctx->frontend, 1, "\r\n", 2);
    }
    sfree(event);

    /*
     * Having either succeeded or failed in opening the log file,
     * we should write any queued data out.
     */
    assert(ctx->state != L_OPENING);   /* make _sure_ it won't be requeued */
    while (bufchain_size(&ctx->queue)) {
	void *data;
	int len;
	bufchain_prefix(&ctx->queue, &data, &len);
	logwrite(ctx, data, len);
	bufchain_consume(&ctx->queue, len);
    }
}
Example #14
0
int main(int argc, char **argv)
{
    char *infile = NULL;
    Filename *infilename = NULL, *outfilename = NULL;
    enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA, ED25519 } keytype = NOKEYGEN;
    char *outfile = NULL, *outfiletmp = NULL;
    enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_AUTO,
           OPENSSH_NEW, SSHCOM } outtype = PRIVATE;
    int bits = -1;
    char *comment = NULL, *origcomment = NULL;
    int change_passphrase = FALSE;
    int errs = FALSE, nogo = FALSE;
    int intype = SSH_KEYTYPE_UNOPENABLE;
    int sshver = 0;
    struct ssh2_userkey *ssh2key = NULL;
    struct RSAKey *ssh1key = NULL;
    unsigned char *ssh2blob = NULL;
    char *ssh2alg = NULL;
    const struct ssh_signkey *ssh2algf = NULL;
    int ssh2bloblen;
    char *old_passphrase = NULL, *new_passphrase = NULL;
    int load_encrypted;
    progfn_t progressfn = is_interactive() ? progress_update : no_progress;
    const char *random_device = NULL;

    /* ------------------------------------------------------------------
     * Parse the command line to figure out what we've been asked to do.
     */

    /*
     * If run with no arguments at all, print the usage message and
     * return success.
     */
    if (argc <= 1) {
	usage(TRUE);
	return 0;
    }

    /*
     * Parse command line arguments.
     */
    while (--argc) {
	char *p = *++argv;
	if (*p == '-') {
	    /*
	     * An option.
	     */
	    while (p && *++p) {
		char c = *p;
		switch (c) {
		  case '-':
		    /*
		     * Long option.
		     */
		    {
			char *opt, *val;
			opt = p++;     /* opt will have _one_ leading - */
			while (*p && *p != '=')
			    p++;	       /* find end of option */
			if (*p == '=') {
			    *p++ = '\0';
			    val = p;
			} else
                            val = NULL;

			if (!strcmp(opt, "-help")) {
                            if (val) {
                                errs = TRUE;
                                fprintf(stderr, "puttygen: option `-%s'"
                                        " expects no argument\n", opt);
                            } else {
                                help();
                                nogo = TRUE;
                            }
			} else if (!strcmp(opt, "-version")) {
                            if (val) {
                                errs = TRUE;
                                fprintf(stderr, "puttygen: option `-%s'"
                                        " expects no argument\n", opt);
                            } else {
                                showversion();
                                nogo = TRUE;
                            }
			} else if (!strcmp(opt, "-pgpfp")) {
                            if (val) {
                                errs = TRUE;
                                fprintf(stderr, "puttygen: option `-%s'"
                                        " expects no argument\n", opt);
                            } else {
                                /* support --pgpfp for consistency */
                                pgp_fingerprints();
                                nogo = TRUE;
                            }
			} else if (!strcmp(opt, "-old-passphrase")) {
			    if (!val && argc > 1)
				--argc, val = *++argv;
			    if (!val) {
				errs = TRUE;
				fprintf(stderr, "puttygen: option `-%s'"
					" expects an argument\n", opt);
			    } else {
				old_passphrase = readpassphrase(val);
				if (!old_passphrase)
				    errs = TRUE;
			    }
			} else if (!strcmp(opt, "-new-passphrase")) {
			    if (!val && argc > 1)
				--argc, val = *++argv;
			    if (!val) {
				errs = TRUE;
				fprintf(stderr, "puttygen: option `-%s'"
					" expects an argument\n", opt);
			    } else {
				new_passphrase = readpassphrase(val);
				if (!new_passphrase)
				    errs = TRUE;
			    }
			} else if (!strcmp(opt, "-random-device")) {
			    if (!val && argc > 1)
				--argc, val = *++argv;
			    if (!val) {
				errs = TRUE;
				fprintf(stderr, "puttygen: option `-%s'"
					" expects an argument\n", opt);
			    } else {
                                random_device = val;
			    }
			} else {
			    errs = TRUE;
			    fprintf(stderr,
				    "puttygen: no such option `-%s'\n", opt);
			}
		    }
		    p = NULL;
		    break;
		  case 'h':
		  case 'V':
		  case 'P':
		  case 'l':
		  case 'L':
		  case 'p':
		  case 'q':
		    /*
		     * Option requiring no parameter.
		     */
		    switch (c) {
		      case 'h':
			help();
			nogo = TRUE;
			break;
		      case 'V':
			showversion();
			nogo = TRUE;
			break;
		      case 'P':
			change_passphrase = TRUE;
			break;
		      case 'l':
			outtype = FP;
			break;
		      case 'L':
			outtype = PUBLICO;
			break;
		      case 'p':
			outtype = PUBLIC;
			break;
		      case 'q':
			progressfn = no_progress;
			break;
		    }
		    break;
		  case 't':
		  case 'b':
		  case 'C':
		  case 'O':
		  case 'o':
		    /*
		     * Option requiring parameter.
		     */
		    p++;
		    if (!*p && argc > 1)
			--argc, p = *++argv;
		    else if (!*p) {
			fprintf(stderr, "puttygen: option `-%c' expects a"
				" parameter\n", c);
			errs = TRUE;
		    }
		    /*
		     * Now c is the option and p is the parameter.
		     */
		    switch (c) {
		      case 't':
			if (!strcmp(p, "rsa") || !strcmp(p, "rsa2"))
			    keytype = RSA2, sshver = 2;
			else if (!strcmp(p, "rsa1"))
			    keytype = RSA1, sshver = 1;
			else if (!strcmp(p, "dsa") || !strcmp(p, "dss"))
			    keytype = DSA, sshver = 2;
                        else if (!strcmp(p, "ecdsa"))
                            keytype = ECDSA, sshver = 2;
                        else if (!strcmp(p, "ed25519"))
                            keytype = ED25519, sshver = 2;
			else {
			    fprintf(stderr,
				    "puttygen: unknown key type `%s'\n", p);
			    errs = TRUE;
			}
                        break;
		      case 'b':
			bits = atoi(p);
                        break;
		      case 'C':
			comment = p;
                        break;
		      case 'O':
			if (!strcmp(p, "public"))
			    outtype = PUBLIC;
			else if (!strcmp(p, "public-openssh"))
			    outtype = PUBLICO;
			else if (!strcmp(p, "private"))
			    outtype = PRIVATE;
			else if (!strcmp(p, "fingerprint"))
			    outtype = FP;
			else if (!strcmp(p, "private-openssh"))
			    outtype = OPENSSH_AUTO, sshver = 2;
			else if (!strcmp(p, "private-openssh-new"))
			    outtype = OPENSSH_NEW, sshver = 2;
			else if (!strcmp(p, "private-sshcom"))
			    outtype = SSHCOM, sshver = 2;
			else {
			    fprintf(stderr,
				    "puttygen: unknown output type `%s'\n", p);
			    errs = TRUE;
			}
                        break;
		      case 'o':
			outfile = p;
                        break;
		    }
		    p = NULL;	       /* prevent continued processing */
		    break;
		  default:
		    /*
		     * Unrecognised option.
		     */
		    errs = TRUE;
		    fprintf(stderr, "puttygen: no such option `-%c'\n", c);
		    break;
		}
	    }
	} else {
	    /*
	     * A non-option argument.
	     */
	    if (!infile)
		infile = p;
	    else {
		errs = TRUE;
		fprintf(stderr, "puttygen: cannot handle more than one"
			" input file\n");
	    }
	}
    }

    if (bits == -1) {
        /*
         * No explicit key size was specified. Default varies
         * depending on key type.
         */
        switch (keytype) {
          case ECDSA:
            bits = 384;
            break;
          case ED25519:
            bits = 256;
            break;
          default:
            bits = DEFAULT_RSADSA_BITS;
            break;
        }
    }

    if (keytype == ECDSA && (bits != 256 && bits != 384 && bits != 521)) {
        fprintf(stderr, "puttygen: invalid bits for ECDSA, choose 256, 384 or 521\n");
        errs = TRUE;
    }

    if (keytype == ED25519 && (bits != 256)) {
        fprintf(stderr, "puttygen: invalid bits for ED25519, choose 256\n");
        errs = TRUE;
    }

    if (keytype == RSA2 || keytype == RSA1 || keytype == DSA) {
        if (bits < 256) {
            fprintf(stderr, "puttygen: cannot generate %s keys shorter than"
                    " 256 bits\n", (keytype == DSA ? "DSA" : "RSA"));
            errs = TRUE;
        } else if (bits < DEFAULT_RSADSA_BITS) {
            fprintf(stderr, "puttygen: warning: %s keys shorter than"
                    " %d bits are probably not secure\n",
                    (keytype == DSA ? "DSA" : "RSA"), DEFAULT_RSADSA_BITS);
            /* but this is just a warning, so proceed anyway */
        }
    }

    if (errs)
	return 1;

    if (nogo)
	return 0;

    /*
     * If run with at least one argument _but_ not the required
     * ones, print the usage message and return failure.
     */
    if (!infile && keytype == NOKEYGEN) {
	usage(TRUE);
	return 1;
    }

    /* ------------------------------------------------------------------
     * Figure out further details of exactly what we're going to do.
     */

    /*
     * Bomb out if we've been asked to both load and generate a
     * key.
     */
    if (keytype != NOKEYGEN && infile) {
	fprintf(stderr, "puttygen: cannot both load and generate a key\n");
	return 1;
    }

    /* 
     * We must save the private part when generating a new key.
     */
    if (keytype != NOKEYGEN &&
	(outtype != PRIVATE && outtype != OPENSSH_AUTO &&
         outtype != OPENSSH_NEW && outtype != SSHCOM)) {
	fprintf(stderr, "puttygen: this would generate a new key but "
		"discard the private part\n");
	return 1;
    }

    /*
     * Analyse the type of the input file, in case this affects our
     * course of action.
     */
    if (infile) {
	infilename = filename_from_str(infile);

	intype = key_type(infilename);

	switch (intype) {
	  case SSH_KEYTYPE_UNOPENABLE:
	  case SSH_KEYTYPE_UNKNOWN:
	    fprintf(stderr, "puttygen: unable to load file `%s': %s\n",
		    infile, key_type_to_str(intype));
	    return 1;

	  case SSH_KEYTYPE_SSH1:
          case SSH_KEYTYPE_SSH1_PUBLIC:
	    if (sshver == 2) {
		fprintf(stderr, "puttygen: conversion from SSH-1 to SSH-2 keys"
			" not supported\n");
		return 1;
	    }
	    sshver = 1;
	    break;

	  case SSH_KEYTYPE_SSH2:
          case SSH_KEYTYPE_SSH2_PUBLIC_RFC4716:
          case SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH:
	  case SSH_KEYTYPE_OPENSSH_PEM:
	  case SSH_KEYTYPE_OPENSSH_NEW:
	  case SSH_KEYTYPE_SSHCOM:
	    if (sshver == 1) {
		fprintf(stderr, "puttygen: conversion from SSH-2 to SSH-1 keys"
			" not supported\n");
		return 1;
	    }
	    sshver = 2;
	    break;

	  case SSH_KEYTYPE_OPENSSH_AUTO:
          default:
            assert(0 && "Should never see these types on an input file");
	}
    }

    /*
     * Determine the default output file, if none is provided.
     * 
     * This will usually be equal to stdout, except that if the
     * input and output file formats are the same then the default
     * output is to overwrite the input.
     * 
     * Also in this code, we bomb out if the input and output file
     * formats are the same and no other action is performed.
     */
    if ((intype == SSH_KEYTYPE_SSH1 && outtype == PRIVATE) ||
	(intype == SSH_KEYTYPE_SSH2 && outtype == PRIVATE) ||
	(intype == SSH_KEYTYPE_OPENSSH_PEM && outtype == OPENSSH_AUTO) ||
	(intype == SSH_KEYTYPE_OPENSSH_NEW && outtype == OPENSSH_NEW) ||
	(intype == SSH_KEYTYPE_SSHCOM && outtype == SSHCOM)) {
	if (!outfile) {
	    outfile = infile;
	    outfiletmp = dupcat(outfile, ".tmp", NULL);
	}

	if (!change_passphrase && !comment) {
	    fprintf(stderr, "puttygen: this command would perform no useful"
		    " action\n");
	    return 1;
	}
    } else {
	if (!outfile) {
	    /*
	     * Bomb out rather than automatically choosing to write
	     * a private key file to stdout.
	     */
	    if (outtype == PRIVATE || outtype == OPENSSH_AUTO ||
                outtype == OPENSSH_NEW || outtype == SSHCOM) {
		fprintf(stderr, "puttygen: need to specify an output file\n");
		return 1;
	    }
	}
    }

    /*
     * Figure out whether we need to load the encrypted part of the
     * key. This will be the case if either (a) we need to write
     * out a private key format, or (b) the entire input key file
     * is encrypted.
     */
    if (outtype == PRIVATE || outtype == OPENSSH_AUTO ||
        outtype == OPENSSH_NEW || outtype == SSHCOM ||
	intype == SSH_KEYTYPE_OPENSSH_PEM ||
	intype == SSH_KEYTYPE_OPENSSH_NEW ||
        intype == SSH_KEYTYPE_SSHCOM)
	load_encrypted = TRUE;
    else
	load_encrypted = FALSE;

    if (load_encrypted && (intype == SSH_KEYTYPE_SSH1_PUBLIC ||
                           intype == SSH_KEYTYPE_SSH2_PUBLIC_RFC4716 ||
                           intype == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH)) {
        fprintf(stderr, "puttygen: cannot perform this action on a "
                "public-key-only input file\n");
        return 1;
    }

    /* ------------------------------------------------------------------
     * Now we're ready to actually do some stuff.
     */

    /*
     * Either load or generate a key.
     */
    if (keytype != NOKEYGEN) {
	char *entropy;
	char default_comment[80];
	struct tm tm;
	struct progress prog;

	prog.phase = -1;
	prog.current = -1;

	tm = ltime();
	if (keytype == DSA)
	    strftime(default_comment, 30, "dsa-key-%Y%m%d", &tm);
        else if (keytype == ECDSA)
            strftime(default_comment, 30, "ecdsa-key-%Y%m%d", &tm);
        else if (keytype == ED25519)
            strftime(default_comment, 30, "ed25519-key-%Y%m%d", &tm);
	else
	    strftime(default_comment, 30, "rsa-key-%Y%m%d", &tm);

	random_ref();
	entropy = get_random_data(bits / 8, random_device);
	if (!entropy) {
	    fprintf(stderr, "puttygen: failed to collect entropy, "
		    "could not generate key\n");
	    return 1;
	}
	random_add_heavynoise(entropy, bits / 8);
	smemclr(entropy, bits/8);
	sfree(entropy);

	if (keytype == DSA) {
	    struct dss_key *dsskey = snew(struct dss_key);
	    dsa_generate(dsskey, bits, progressfn, &prog);
	    ssh2key = snew(struct ssh2_userkey);
	    ssh2key->data = dsskey;
	    ssh2key->alg = &ssh_dss;
	    ssh1key = NULL;
        } else if (keytype == ECDSA) {