From mboxrd@z Thu Jan 1 00:00:00 1970 From: James Antill Subject: Re: [RFC: PATCH] Audit Failure Query Functionality Date: Tue, 13 Jun 2006 17:30:46 -0400 Message-ID: <1150234246.29837.29.camel@code.and.org> References: <448F096E.8060703@hp.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1166274857==" Return-path: In-Reply-To: <448F096E.8060703@hp.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: redhat-lspp-bounces@redhat.com Errors-To: redhat-lspp-bounces@redhat.com To: Lisa Smith Cc: LSPP , linux-audit@redhat.com List-Id: linux-audit@redhat.com --===============1166274857== Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="=-DnXNdPttPH/LsgNrqsew" --=-DnXNdPttPH/LsgNrqsew Content-Type: text/plain Content-Transfer-Encoding: quoted-printable On Tue, 2006-06-13 at 14:52 -0400, Lisa Smith wrote: > This is this initial patch for the audit failure query functionality. [...] > libaudit.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > libaudit.h | 25 ++++++++ > 2 files changed, 188 insertions(+) >=20 > diff -burN orig/libaudit.c src/libaudit.c > --- orig/libaudit.c 2006-05-25 17:39:52.000000000 -0400 > +++ src/libaudit.c 2006-06-13 14:46:33.000000000 -0400 > @@ -68,6 +68,169 @@ > return rc; > } >=20 > +/* > + * This function will retrieve the audit failure tunable value > + * from the filename passed in. If no file is specified, the default > + * /etc/libaudit.conf file will be used. > + */ > +auditfail_t audit_failure_action(char *file) > +{ > + int ret; > + struct nv_pair nv; > + > + if (file =3D=3D NULL) > + file =3D AUDIT_FAIL_CONFIG; > + > + /* Find the audit failure action tunable in the config file */ > + ret =3D search_audituser_conf(file, AUDIT_FAIL_KEYWORD, &nv); > + > + if (ret =3D=3D -1) { > + audit_msg(LOG_WARNING, "Error in %s", file); > + return ERR; > + } else if (ret =3D=3D 1) { > + /* Keyword not found, so do the default action */ > + return IGNORE; > + } > + > + /* Translate tunable string to valid enum */ > + if (strncmp(nv.value, AUDIT_FAIL_IGNORE, > + strlen(AUDIT_FAIL_IGNORE)) =3D=3D 0) { This means that "ignores" will be valid, as will "logout". > + free (nv.name); > + free (nv.value); > + return IGNORE; > + } [...] > +/* > + * This function searches for a keyword pair in the passed in filename. > + * If the keyword pair is found, it is saved in the nv structure and zer= o > + * is returned. If the file can not be opened, -1 is returned. > + * If the keyword is not found in the file, 1 is returned. > + * > + * nv->name and nv->value must be freed if an error will be returned fro= m this > + * function after nv_split() is called. If this function returns success= , > + * the caller must free nv->name and nv->value when finished using the > + * values. > + */ > +int search_audituser_conf(char *file, char *keyword, struct nv_pair *nv) > +{ > + int rc, lineno =3D 1; > + size_t len =3D 0; > + ssize_t bytesread; > + FILE *fp; > + char *buf =3D NULL; > + > + /* Open the file for line by line reading*/ > + fp =3D fopen(file, "r"); > + if (fp =3D=3D NULL) { > + audit_msg(LOG_ERR, "Error - fdopen failed for %s (%s)", > + file, strerror(errno)); > + return -1; > + } > + > + while ((bytesread =3D getline(&buf, &len, fp)) !=3D -1) { > + > + if (buf[0] =3D=3D '#') { > + lineno++; > + continue; // Ignore comments > + } > + > + /* Convert line into name-value pair */ > + rc =3D nv_split(buf, nv); The values in nv are leaked when there isn't a match or an error. > + if (rc =3D=3D 1) { > + audit_msg(LOG_ERR, "Error on line %d in %s", line= no, > + file); > + lineno++; > + continue; > + } > + > + /* Find the name-value pair */ > + if (strcmp(nv->name, keyword) =3D=3D 0) > + { > + fclose(fp); > + if (buf) > + free (buf); > + return 0; > + } > + > + lineno++; > + } > + > + /* If we get here, the keyword was not found in the file */ > + audit_msg(LOG_ERR, "Keyword %s not found in %s", keyword, file); > + fclose(fp); > + if (buf) > + free (buf); > + if (nv->name) > + free (nv->name); > + if (nv->value) > + free (nv->value); > + return 1; > +} > + > +/* > + * This function parses a line looking for a keyword =3D value pair > + * and if found, returns it in the nv structure. If the function > + * returns success, the calling function is expected to free > + * nv->name and nv->value. > + */ > +int nv_split(char *buffer, struct nv_pair *nv) > +{ > + /* Get the name part */ > + char *saveptr, *ptr =3D NULL; > + char *buf =3D strdup(buffer); This is always leaked. > + > + /* Look for =3D in buf */ > + nv->name =3D NULL; > + nv->value =3D NULL; > + ptr =3D strtok_r(buf, " =3D", &saveptr); > + if ((ptr =3D=3D NULL) || !(strcmp(ptr,"\n"))) { > + return 0; // If there's nothing, go to next line > + } > + nv->name =3D strdup(ptr); > + > + /* Get the keyword value */ > + ptr =3D strtok_r(NULL, " =3D", &saveptr); I appreciate this is somewhat easier given C's default string API, but it would be really nice to do the right thing if the user uses "x=3Dy" instead of needing "x =3Dy". This also isn't how auditd parses the it's file. > + if (ptr =3D=3D NULL) { > + free (nv->name); > + return 1; > + } > + nv->value =3D strdup(ptr); > + > + /* Make sure there's nothing else on the line */ > + ptr =3D strtok_r(NULL, " ", &saveptr); > + if (ptr) { > + free (nv->name); > + free (nv->value); > + return 1; > + } > + > + /* Everything is OK */ > + return 0; > +} > + > + > + > int audit_set_enabled(int fd, uint32_t enabled) > { > int rc; > diff -burN orig/libaudit.h src/libaudit.h > --- orig/libaudit.h 2006-05-25 17:38:21.000000000 -0400 > +++ src/libaudit.h 2006-06-13 13:01:30.000000000 -0400 > @@ -248,6 +248,28 @@ > MACH_ALPHA > } machine_t; >=20 > +/* These are the valid audit failure tunable enum values */ > +typedef enum { > + ERR=3D-1, > + IGNORE=3D0, > + LOG, > + TERM > +} auditfail_t; These enum values should be namespaced esp. as they are very generic names. > + > +/* #defines for the audit failure query */ > +#define AUDIT_FAIL_CONFIG "/etc/libaudit.conf" > +#define AUDIT_FAIL_KEYWORD "auditfailure" > +#define AUDIT_FAIL_IGNORE "ignore" > +#define AUDIT_FAIL_LOG "log" > +#define AUDIT_FAIL_TERM "terminate" > + > +/* Name-value pair */ > +struct nv_pair > +{ > + char *name; > + char *value; > +}; > + This should be namespaced. > /* > * audit_rule_data supports filter rules with both integer and string > * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and > @@ -362,6 +384,9 @@ > /* AUDIT_GET */ > extern int audit_request_status(int fd); > extern int audit_is_enabled(int fd); > +extern auditfail_t audit_failure_action(char *file); > +static int search_audituser_conf(char *file, char *keyword, struct nv_pa= ir *nv); > +static int nv_split(char *buf, struct nv_pair *nv); These shouldn't be in the public .h file. > /* AUDIT_SET */ > typedef enum { WAIT_NO, WAIT_YES } rep_wait_t; Could these be namespaced too? --=20 James Antill --=-DnXNdPttPH/LsgNrqsew Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.3 (GNU/Linux) iD8DBQBEjy6G11eXTEMrxtQRAvDwAJ9g/YlhzJovsczY9Gh6ROTaA5k/HgCeKYeF 3ZXZxwp3ZTFPAeqy8DERbko= =aTA7 -----END PGP SIGNATURE----- --=-DnXNdPttPH/LsgNrqsew-- --===============1166274857== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline --===============1166274857==--