155682Smarkm/* 2233294Sstas * Copyright (c) 1997-2004 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "ktutil_locl.h" 3555682Smarkm 36233294SstasRCSID("$Id$"); 3755682Smarkm 3855682Smarkm/* 3955682Smarkm * keep track of the highest version for every principal. 4055682Smarkm */ 4155682Smarkm 4255682Smarkmstruct e { 4355682Smarkm krb5_principal principal; 4455682Smarkm int max_vno; 45178825Sdfr time_t timestamp; 4655682Smarkm struct e *next; 4755682Smarkm}; 4855682Smarkm 4955682Smarkmstatic struct e * 5055682Smarkmget_entry (krb5_principal princ, struct e *head) 5155682Smarkm{ 5255682Smarkm struct e *e; 5355682Smarkm 5455682Smarkm for (e = head; e != NULL; e = e->next) 5555682Smarkm if (krb5_principal_compare (context, princ, e->principal)) 5655682Smarkm return e; 5755682Smarkm return NULL; 5855682Smarkm} 5955682Smarkm 6055682Smarkmstatic void 61178825Sdfradd_entry (krb5_principal princ, int vno, time_t timestamp, struct e **head) 6255682Smarkm{ 6355682Smarkm krb5_error_code ret; 6455682Smarkm struct e *e; 6555682Smarkm 6655682Smarkm e = get_entry (princ, *head); 6755682Smarkm if (e != NULL) { 68178825Sdfr if(e->max_vno < vno) { 69178825Sdfr e->max_vno = vno; 70178825Sdfr e->timestamp = timestamp; 71178825Sdfr } 7255682Smarkm return; 7355682Smarkm } 7455682Smarkm e = malloc (sizeof (*e)); 7555682Smarkm if (e == NULL) 7655682Smarkm krb5_errx (context, 1, "malloc: out of memory"); 7755682Smarkm ret = krb5_copy_principal (context, princ, &e->principal); 7855682Smarkm if (ret) 7955682Smarkm krb5_err (context, 1, ret, "krb5_copy_principal"); 8055682Smarkm e->max_vno = vno; 81178825Sdfr e->timestamp = timestamp; 8255682Smarkm e->next = *head; 8355682Smarkm *head = e; 8455682Smarkm} 8555682Smarkm 8655682Smarkmstatic void 8755682Smarkmdelete_list (struct e *head) 8855682Smarkm{ 8955682Smarkm while (head != NULL) { 9055682Smarkm struct e *next = head->next; 9155682Smarkm krb5_free_principal (context, head->principal); 9255682Smarkm free (head); 9355682Smarkm head = next; 9455682Smarkm } 9555682Smarkm} 9655682Smarkm 9755682Smarkm/* 9855682Smarkm * Remove all entries that have newer versions and that are older 9955682Smarkm * than `age' 10055682Smarkm */ 10155682Smarkm 10255682Smarkmint 103178825Sdfrkt_purge(struct purge_options *opt, int argc, char **argv) 10455682Smarkm{ 10578527Sassar krb5_error_code ret = 0; 10655682Smarkm krb5_kt_cursor cursor; 10778527Sassar krb5_keytab keytab; 10855682Smarkm krb5_keytab_entry entry; 10972445Sassar int age; 11055682Smarkm struct e *head = NULL; 11155682Smarkm time_t judgement_day; 11255682Smarkm 113178825Sdfr age = parse_time(opt->age_string, "s"); 11472445Sassar if(age < 0) { 115178825Sdfr krb5_warnx(context, "unparasable time `%s'", opt->age_string); 11678527Sassar return 1; 11772445Sassar } 11872445Sassar 11990926Snectar if((keytab = ktutil_open_keytab()) == NULL) 12078527Sassar return 1; 12178527Sassar 12255682Smarkm ret = krb5_kt_start_seq_get(context, keytab, &cursor); 12355682Smarkm if(ret){ 124178825Sdfr krb5_warn(context, ret, "%s", keytab_string); 12578527Sassar goto out; 12655682Smarkm } 12755682Smarkm 128233294Sstas while(krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0) { 129178825Sdfr add_entry (entry.principal, entry.vno, entry.timestamp, &head); 13055682Smarkm krb5_kt_free_entry(context, &entry); 13155682Smarkm } 132233294Sstas krb5_kt_end_seq_get(context, keytab, &cursor); 13355682Smarkm 13455682Smarkm judgement_day = time (NULL); 13555682Smarkm 13655682Smarkm ret = krb5_kt_start_seq_get(context, keytab, &cursor); 13755682Smarkm if(ret){ 138178825Sdfr krb5_warn(context, ret, "%s", keytab_string); 13978527Sassar goto out; 14055682Smarkm } 14155682Smarkm 142233294Sstas while(krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0) { 14355682Smarkm struct e *e = get_entry (entry.principal, head); 14455682Smarkm 14555682Smarkm if (e == NULL) { 14655682Smarkm krb5_warnx (context, "ignoring extra entry"); 14755682Smarkm continue; 14855682Smarkm } 14955682Smarkm 15055682Smarkm if (entry.vno < e->max_vno 151178825Sdfr && judgement_day - e->timestamp > age) { 15255682Smarkm if (verbose_flag) { 15355682Smarkm char *name_str; 15455682Smarkm 15555682Smarkm krb5_unparse_name (context, entry.principal, &name_str); 15655682Smarkm printf ("removing %s vno %d\n", name_str, entry.vno); 15755682Smarkm free (name_str); 15855682Smarkm } 15955682Smarkm ret = krb5_kt_remove_entry (context, keytab, &entry); 16055682Smarkm if (ret) 16155682Smarkm krb5_warn (context, ret, "remove"); 16255682Smarkm } 16355682Smarkm krb5_kt_free_entry(context, &entry); 16455682Smarkm } 16555682Smarkm ret = krb5_kt_end_seq_get(context, keytab, &cursor); 16655682Smarkm 16755682Smarkm delete_list (head); 16855682Smarkm 16978527Sassar out: 17078527Sassar krb5_kt_close (context, keytab); 17178527Sassar return ret != 0; 17255682Smarkm} 173