diff options
author | seb <none@none> | 2007-08-13 08:33:13 -0700 |
---|---|---|
committer | seb <none@none> | 2007-08-13 08:33:13 -0700 |
commit | 35076d53642115be972f548db8761effee923cf8 (patch) | |
tree | f9e11ecb9c2d9dd37d7f405de92e1c3cb91f0f5b /deleted_files | |
parent | d577a05052763490983ba19d548a252fed6f75d9 (diff) | |
download | illumos-gate-35076d53642115be972f548db8761effee923cf8.tar.gz |
6479886 mipagent and related kernel interfaces should be removed (fix unref)
--HG--
rename : usr/src/cmd/cmd-inet/common/conflib.c => deleted_files/usr/src/cmd/cmd-inet/common/conflib.c
rename : usr/src/cmd/cmd-inet/common/conflib.h => deleted_files/usr/src/cmd/cmd-inet/common/conflib.h
Diffstat (limited to 'deleted_files')
-rw-r--r-- | deleted_files/usr/src/cmd/cmd-inet/common/conflib.c | 2116 | ||||
-rw-r--r-- | deleted_files/usr/src/cmd/cmd-inet/common/conflib.h | 122 |
2 files changed, 2238 insertions, 0 deletions
diff --git a/deleted_files/usr/src/cmd/cmd-inet/common/conflib.c b/deleted_files/usr/src/cmd/cmd-inet/common/conflib.c new file mode 100644 index 0000000000..b2d4014adc --- /dev/null +++ b/deleted_files/usr/src/cmd/cmd-inet/common/conflib.c @@ -0,0 +1,2116 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This file implements windows style INI files. It caches + * files in memory, so they are not parsed on each read. + * + * WARNING: This library is completely UN-THREAD-SAFE and NON-REENTRANT. + */ + +/* LINTLIBRARY */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <strings.h> +#include <string.h> +#include <ctype.h> +#include <sys/stat.h> +#include <net/pfkeyv2.h> /* ipsec alg, etc., values */ +#include <errno.h> + +#include "conflib.h" + +#define INI_MAX_CACHED 10 /* Maximum number of files to keep cached */ +#define MAX_LONG_LEN 20 /* The printed size of a 32 bit number */ + +/* ********************* Internal Structures ******************** */ + +/* This is the simplest part. A label. This is the atom of the ini file */ +typedef struct { + char Label[MAX_LABEL_LEN]; + char Value[MAX_VALUE_LEN]; +} LabelType; + +/* A section contains an array list of labels */ +typedef struct { + int NumLabels; + char SectionName[MAX_FILENAME_LEN]; + LabelType *Labels; +} SectionType; + +/* An ini file contains an array list of Sections */ +typedef struct { + int NumSections; + char Filename[MAX_FILENAME_LEN]; + time_t ModificationTime; + SectionType *Sections; +} IniFileType; + +/* An IniFileList Contains a linked list of ini files */ +typedef struct s { + IniFileType IniFile; + struct s *Next; +} IniFileList; + +static IniFileList *IniHead = NULL; + +#define BUF_LEN MAX_LABEL_LEN + MAX_VALUE_LEN +#define INI_SECTION 1 +#define INI_LABEL 2 +#define INI_ERROR 0 + +char ErrorString[ERROR_STRING_LEN]; + +boolean_t encr_alg_set = FALSE; /* true if encr_alg set */ + +/* These are the valid ipsec actions mipagent and friends support. */ +char *validIPsecAction[] = { + "apply", /* outbound IPsec Policy */ + "permit", /* inbound IPsec Policy */ + NULL +}; + +/* Each entry in our various ipsec algorithm tables is one of these */ +struct ipsec_alg { + char *alg; + uint_t value; +}; + +/* Some macroed values */ +#define NO_AH_AALG 256 +#define NO_ESP_AALG 256 +#define NO_ESP_EALG 256 + +/* valid encr_algs to match with user config */ +struct ipsec_alg encr_algs[] = { + {"any", SADB_EALG_NONE}, + {"des", SADB_EALG_DESCBC}, + {"des-cbc", SADB_EALG_DESCBC}, + {"3des", SADB_EALG_3DESCBC}, + {"3des-cbc", SADB_EALG_3DESCBC}, + {"blowfish", SADB_EALG_BLOWFISH}, + {"blowfish-cbc", SADB_EALG_BLOWFISH}, + {"aes", SADB_EALG_AES}, + {"aes-cbc", SADB_EALG_AES}, + {"null", SADB_EALG_NULL}, + {"none", NO_ESP_EALG}, + {NULL, 0} +}; + +/* one auth_algs to match with user configs */ +struct ipsec_alg auth_algs[] = { + {"any", SADB_AALG_NONE}, + {"md5", SADB_AALG_MD5HMAC}, + {"hmac-md5", SADB_AALG_MD5HMAC}, + {"sha1", SADB_AALG_SHA1HMAC}, + {"hmac-sha1", SADB_AALG_SHA1HMAC}, + {"sha", SADB_AALG_SHA1HMAC}, + {"hmac-sha", SADB_AALG_SHA1HMAC}, + {"none", NO_AH_AALG}, + {NULL, 0} +}; + +#define SADB_SA_SHARED 0 +#define SADB_SA_UNIQUE 1 + +/* + * One for sa_algs. OK, these aren't algs, but in order to make the parsing + * of properties easy, they're laid out "<tag> <alg> <tag> <alg> ...", so it's + * designed so <tag> maps directly to the function that parses <alg>. The + * "... sa (shared | unique)" bit then needs to be done analogously. + */ +struct ipsec_alg sa_algs[] = { + {"shared", SADB_SA_SHARED}, + {"unique", SADB_SA_UNIQUE}, + {NULL, 0}, +}; + + +/* + * Internal prototypes + */ +static int IniLoadFile(char *Filename); +static void InitializeIniFile(IniFileList *FileList); +static int IniParseFile(IniFileType *File, char *Filename); +static int AddSection(IniFileType *IniFile, char *Section); +static int AddLabel(IniFileType *IniFile, int SectionNdx, char *Label, + char *Data); +static void ModifyLabel(IniFileType *IniFile, int SectionNdx, int LabelNdx, + char *Data); +static int IniCheckComment(char *buffer); +static int ParseLine(char *buffer, char *TempLabel, char *TempValue); +static int IniLoaded(char *Filename); +static int IniUpdateLocalCopy(char *Filename, char *Section, char *Label, + char *Data); +#ifndef lint /* this function is not used for now */ +static char *GetSectionList(IniFileType *IniFile, char *argv, int *NumSections, + int *elementSize); +#endif /* lint */ +static IniFileList *UnlinkFile(char *Filename); +static int IniUnloadFile(char *Filename); +static int IniUpdateFile(char *Filename, char *Section, char *Label, + char *Data); +static int CopyToSection(char *Section, FILE *in, FILE *out, int CopySection); +static void CopyToEOF(FILE *in, FILE *out, char *Label); +static char *dirname(char *FullPath); +static void CheckAndAllocateCacheSpace(); +static void IniFreeFile(IniFileList *File); +static int Rename(char *source, char *dest); +static int GetSectionProfileString(IniFileList *IniFile, char *Section, + char *Label, char *dest, int destLen); +static int GetLabelProfileString(IniFileList *IniFile, int SectionNdx, + char *Label, char *dest, int destLen); + +/* ipsec algorithm parsing routines */ +int parsealg(char *, struct ipsec_alg *); +int parse_algs(int, int, ipsec_req_t *); +int parse_esp_auth_alg(char *, ipsec_req_t *); +int parse_esp_encr_alg(char *, ipsec_req_t *); +int parse_ah_alg(char *, ipsec_req_t *); +int parse_sa_alg(char *, ipsec_req_t *); +uint_t isIPsecActionValid(char *); + + +/* something to switch on */ +enum ipsec_alg_type { ESP_ENCR_ALG = 1, ESP_AUTH_ALG, AH_AUTH_ALG, SA_ALG }; + +/* table for parsing IPSEC related algs */ +struct ipsec_cmd { + char *c_name; + int (*c_func)(char *, ipsec_req_t *); +} ipseccmd[] = { + { "encr_auth_algs", parse_esp_auth_alg }, + { "encr_algs", parse_esp_encr_alg }, + { "auth_algs", parse_ah_alg }, + { "sa", parse_sa_alg }, + { 0, 0 }, +}; + + +/* + * Function: InitializeIniFile + * + * Arguments: IniFileList * + * + * Description: This function will Initialize an ini file + * + * Returns: void + * + */ +static void +InitializeIniFile(IniFileList *New) +{ + New->Next = NULL; + New->IniFile.NumSections = 0; + (void) memset(New->IniFile.Filename, 0, MAX_FILENAME_LEN); + New->IniFile.ModificationTime = 0; + New->IniFile.Sections = NULL; +} /* InitializeIniFile */ + +/* + * Function: FileHasChanged + * + * Arguments: ModificationTime, Filename + * + * Description: This function will return true if the filename's + * modification time is different than the one passed in. + * It also returns true on error. If we aren't able to get a + * stat() of the file, just assume it has changed. + * + * Returns: int (non zero if time has changed) + * + */ +static int +FileHasChanged(time_t ModificationTime, char *Filename) +{ + struct stat file_stats; + + if (stat(Filename, &file_stats) == (-1)) { + char *errMsg = strerror(errno); + + if (errno == ENOENT) + return (TRUE); /* file does not exist */ + + /* + * Some kind of error. Just return TRUE. + * Note: we come in here twice, once via IniLoaded(), and + * (if that fails) again from IniLoadFile(). It would be + * mostly innocuous to overwrite ErrorString with this [same] + * message, but why bother? + */ + if (ErrorString[0] == '\0') { + snprintf(ErrorString, sizeof (ErrorString), "Warning: " + "unable to retrieve stats on <%s>. %s.", Filename, + errMsg != NULL ? errMsg : "Unknown error"); + } + + return (TRUE); + } + + /* + * Now return the change state + */ + return (ModificationTime != file_stats.st_mtime); +} /* FileHasChanged */ + +/* + * Function: IniLoadFile + * + * Arguments: Filename + * + * Description: This function loads in a configuration file. + * It caches files by moving them to the head of the linked + * list. It also checks for files that have changed on the disk + * by using stat(). + * + * Returns: int (zero on success) + * + */ +static int +IniLoadFile(char *Filename) +{ + IniFileList *NewIniFileNode, *Probe; + IniFileList *Last = NULL; + + for (Probe = IniHead; Probe; Probe = Probe->Next) { + /* Check to see if it is already loaded */ + if (strcmp(Probe->IniFile.Filename, Filename) == 0) { + /* + * Found it, we already have it cached. + * check Date/Time stamp + */ + if (FileHasChanged(Probe->IniFile. + ModificationTime, Filename)) { + /* Reload the file */ + (void) IniUnloadFile(Filename); + break; /* Leave loop */ + } else { + /* + * It is our file, and it hasn't changed, + * Cache our entry by moving it to the head + * of the list and return success. + */ + if (Last) { + /* + * Only move it if this is not the + * first entry. + */ + Last->Next = Probe->Next; + Probe->Next = IniHead; + IniHead = Probe; + } + return (0); + } + } /* strcmp checking filename */ + Last = Probe; + } /* For loop searching for file */ + + /* + * Now, we know that we don't have the file cached or loaded, so + * allocate memory and load it. + * Note: IniFileList is the bucket that holds a STATIC IniFileType. + */ + NewIniFileNode = malloc(sizeof (IniFileList)); + if (!NewIniFileNode) { + (void) strcpy(ErrorString, + "Unable to allocate memory for new ini file."); + return (-1); + } + + /* + * Add it to our head. But first, remove the last entry if we have + * Too many items in our cache. + */ + CheckAndAllocateCacheSpace(); + NewIniFileNode->Next = IniHead; + IniHead = NewIniFileNode; + + /* + * Now we have a pointer to New. Clear it, and parse in the + * new file + */ + InitializeIniFile(NewIniFileNode); + if (IniParseFile(&NewIniFileNode->IniFile, Filename)) { + /* Remove ini file from list */ + IniHead = NewIniFileNode->Next; + free(NewIniFileNode); + return (-2); + } + + return (0); +} /* IniLoadFile */ + +/* + * Function: CheckAndAllocateCacheSpace + * + * Arguments: none + * + * Description: This routine will check to see if our INI cache is full, and + * if so, will delete the last (least recently used) entry. + * + * Returns: void + * + */ +static void +CheckAndAllocateCacheSpace() +{ + IniFileList *Probe; + IniFileList *Last; + int count; + + /* Return if the cache is empty (or nearly empty) */ + if (!IniHead || !IniHead->Next) + return; + + /* + * Send Probe to next to end of list, and last to one before probe, + * while counting with count. + */ + for (Probe = IniHead, count = 0, Last = IniHead; + Probe->Next; + Probe = Probe->Next, count++) + Last = Probe; + + if (count >= INI_MAX_CACHED) { + /* Our cache is full. Free the last entry */ + Last->Next = NULL; + IniFreeFile(Probe); + } +} /* CheckAndAllocateCacheSpace */ + +/* + * Function: IniParseFile + * + * Arguments: IniFileType *File, char *Filename + * + * Description: This routine will parse the INI file and load the Section + * and Label arrays. + * + * Returns: int + */ +static int +IniParseFile(IniFileType *File, char *Filename) +{ + int LineNo; + char CurrentSection[MAX_LABEL_LEN]; + char buffer[BUF_LEN]; + char TempLabel[MAX_LABEL_LEN], TempValue[MAX_VALUE_LEN]; + FILE *handle; + int rc; + struct stat file_stat; + + /* + * Copy the filename... + */ + (void) strncpy(File->Filename, Filename, MAX_FILENAME_LEN); + File->Filename[MAX_FILENAME_LEN-1] = 0; /* Just in case we overran */ + + (void) memset(CurrentSection, 0, MAX_LABEL_LEN); + + /* Set the modification time */ + if (stat(Filename, &file_stat) == 0) { + File->ModificationTime = file_stat.st_mtime; + } else { + char *errMsg = strerror(errno); + + (void) snprintf(ErrorString, sizeof (ErrorString), + "Unable to stat <%s>. %s.", Filename, + errMsg != NULL ? errMsg : "Unknown error"); + + return (-1); + } + + /* Open the file */ + handle = fopen(Filename, "rt"); + if (handle == NULL) { + char *errMsg = strerror(errno); + + (void) snprintf(ErrorString, sizeof (ErrorString), + "Unable to open file <%s>. %s.", Filename, + errMsg != NULL ? errMsg : "Unknown error"); + + return (-1); + } + + LineNo = 0; + while (fgets(buffer, BUF_LEN, handle)) { + LineNo++; + /* If it is a comment or a blank line, don't process it */ + if (IniCheckComment(buffer)) + continue; + + switch (ParseLine(buffer, TempLabel, TempValue)) { + case INI_SECTION: + /* Call our add section function */ + rc = AddSection(File, TempLabel); + /* If an error occurs, AddSection sets ErrorString */ + if (rc < 0) { + (void) fclose(handle); + return (rc); + } + break; + + case INI_LABEL: + /* + * check to see if we are before our first + * section label + */ + if (!File->NumSections) { + (void) sprintf(ErrorString, "Data outside of " + "section on line %d.", LineNo); + (void) fclose(handle); + return (-2); + } + rc = AddLabel(File, File->NumSections-1, TempLabel, + TempValue); + /* If an error occurs, AddLabel sets ErrorString */ + if (rc < 0) { + (void) fclose(handle); + return (rc); + } + break; + case INI_ERROR: + default: + (void) snprintf(ErrorString, sizeof (ErrorString), + "Error parsing INI file (%s) on line %d.", + Filename, LineNo); + (void) fclose(handle); + return (-3); + } + } + + /* Success! */ + (void) fclose(handle); + return (0); +} /* IniParseFile */ + +/* + * Function: TrimWhiteSpace + * + * Arguments: char *buffer + * + * Description: This function removes leading and trailing white space + * from a string. + * + * Returns: static void + */ +static void +TrimWhiteSpace(char *buffer) +{ + int i, j; + /* First, find first non-whitespace character */ + for (i = 0; buffer[i] && isspace((int)buffer[i]); i++); + + /* + * Now, i is pointing to the first non-white space + * character in buffer + */ + + /* Find the last non-whitespace character */ + for (j = strlen(buffer)-1; j > 0 && isspace((int)buffer[j]); j--); + + if ((i > j) || (j < 0)) { + /* Empty */ + buffer[0] = 0; + } else { + /* copy the usable buffer */ + bcopy(&buffer[i], buffer, (j-i)+1); + /* and Null-terminate it */ + buffer[(j-i)+1] = 0; + } +} /* TrimWhiteSpace */ + +/* + * Function: ParseLine + * + * Arguments: char *buffer, char *TempTag, char *TempValue + * + * Description: This routine will return either the section or label + * information. If it finds a section line in the buffer, + * it will return the section name in the TempTag Field. + * If it finds a Label, it will fill out TempValue and + * TempTag. + * + * Returns: int + */ +static int +ParseLine(char *staticBuffer, char *TempTag, char *TempValue) +{ + int i = 0, j = 0; + int EqualFound = FALSE; + char buffer[BUF_LEN]; + + (void) strlcpy(buffer, staticBuffer, BUF_LEN); + + /* Trim the white space of the entire buffer first */ + TrimWhiteSpace(buffer); + + if (buffer[0] == '[') { + /* Must be a section */ + for (i = 1; buffer[i] && buffer[i] != ']'; i++) + TempTag[j++] = buffer[i]; + + /* Check to make sure we got an end-bracket */ + if (buffer[i] != ']') + /* Bad Section! */ + return (INI_ERROR); + + TempTag[j] = 0; + TrimWhiteSpace(TempTag); + return (INI_SECTION); + } + for (i = 0; buffer[i]; i++) { + if (buffer[i] == '=') { + EqualFound = TRUE; + TempTag[j] = 0; + j = 0; + } else { + if (!EqualFound) + TempTag[j++] = buffer[i]; + else + TempValue[j++] = buffer[i]; + } + } + if (!EqualFound) { + /* Bad Label! */ + return (INI_ERROR); + } + TempValue[j] = 0; + /* Handle EOLN */ + if (TempValue[j-1] == '\n') + TempValue[j-1] = 0; + + /* And finally, trim the white space off of our return strings */ + TrimWhiteSpace(TempTag); + TrimWhiteSpace(TempValue); + return (INI_LABEL); +} /* ParseLine */ + + +/* + * Function: IniUpdateFile + * + * Arguments: char *Filename, char *Section, char *Label, char *Data + * + * Description: This will update our INI file. It copies the file from + * it's original position to a temp one, then renames to + * overwrite the original. + * + * Returns: int (zero on success) + */ +static int +IniUpdateFile(char *Filename, char *Section, char *Label, char *Data) +{ + FILE *in, *out; + char TempFile[MAX_FILENAME_LEN]; + int DeleteSection = 0; + int DeleteLabel = 0; + + /* Set our deletion flags */ + if (!Label && !Data) + DeleteSection = 1; + + if (!Data) + DeleteLabel = 1; + + /* + * Don't worry about checking the handle right away. It's checked + * later. If the input file open fails, we assume that the file just + * does not exist. It will be created when the output file is renamed + * into the input file (or it is copied). + */ + in = fopen(Filename, "r+"); + + /* Create a temporary file name in the same directory as the INI file */ + (void) strlcpy(TempFile, tempnam(dirname(Filename), NULL), + sizeof (TempFile)); + + out = fopen(TempFile, "w"); + if (!out) { + char *errMsg = strerror(errno); + + (void) snprintf(ErrorString, sizeof (ErrorString), + "Unable to copy <%s>, can't open temp file <%s>. %s.", + Filename, TempFile, + errMsg != NULL ? errMsg : "Unknown error"); + + (void) fclose(in); + return (-1); + } + + if (in) { + /* Our input file exists */ + if (!CopyToSection(Section, in, out, DeleteSection?0:1)) { + /* + * Section did not exist, make one + * If DeleteSection or DeleteLabel is set, it's a nop. + */ + + if (!DeleteSection && !DeleteLabel) { + (void) fprintf(out, "[%s]\n", Section); + (void) fprintf(out, "%s=%s\n", Label, Data); + } + } else { + if (DeleteSection) { + /* + * Delete the section. + * Copy to EOF with NULL as the label + */ + CopyToEOF(in, out, NULL); + } else { + /* + * Section did exist, just dump label, and + * search for next section or same label line, + * so we can erase it. + */ + if (!DeleteLabel) { + /* + * Dump the new label, only if + * we're not deleting it + */ + (void) fprintf(out, "%s=%s\n", + Label, Data); + } + CopyToEOF(in, out, Label); + } + } + (void) fclose(in); + } else { + /* no input file, just put output */ + (void) fprintf(out, "[%s]\n", Section); + (void) fprintf(out, "%s=%s\n", Label, Data); + } + + (void) fclose(out); + /* + * The rename could file for many reasons, but all of them are very + * bad ones. Assume that Rename has set ErrorString. + */ + if (Rename(TempFile, Filename)) { + return (-1); + } + /* Let our internal update set the return code now */ + return (IniUpdateLocalCopy(Filename, Section, Label, Data)); +} /* IniUpdateFile */ + +/* + * Function: Rename + * + * Arguments: char *source, char *dest + * + * Description: This function tries a rename. If it fails, it tries a copy. + * It should never fail, since the temp file is in the same + * directory as the input file. + * + * Returns: int (zero on success) + */ +int +Rename(char *source, char *dest) +{ + int rc; + if ((rc = rename(source, dest)) != 0) { + /* Do copy! */ + FILE *in, *out; + char buffer[BUFSIZ]; /* use the system BUFSIZ for efficiency */ + int nchars; + + in = fopen(source, "r"); + if (!in) { + char *errMsg = strerror(errno); + + (void) snprintf(ErrorString, sizeof (ErrorString), + "Error opening source file <%s> for rename. %s.", + source, errMsg != NULL ? errMsg : "Unknown error"); + + return (-1); + } + out = fopen(dest, "w"); + if (!out) { + char *errMsg = strerror(errno); + + (void) fclose(in); + (void) unlink(dest); + (void) snprintf(ErrorString, sizeof (ErrorString), + "Error opening target file <%s> for rename. %s.", + dest, errMsg != NULL ? errMsg : "Unknown error"); + + return (-2); + } + + /* Ok, now do copy */ + do { + nchars = fread(buffer, 1, BUFSIZ, in); + if (nchars > 0) { + rc = fwrite(buffer, 1, nchars, out); + if (rc != nchars) { + char *errMsg = strerror(errno); + + (void) snprintf(ErrorString, + sizeof (ErrorString), + "Error writing target file <%s> " + "during rename. %s.", dest, + errMsg != NULL ? errMsg : + "Unknown error."); + + (void) fclose(in); + (void) fclose(out); + (void) unlink(source); + return (rc); + } + } + } while (nchars > 0); + + /* if fread() fails... */ + if (nchars < 0) { + char *errMsg = strerror(errno); + + (void) snprintf(ErrorString, sizeof (ErrorString), + "Error reading source file <%s>. %s.", source, + errMsg != NULL ? errMsg : "Unknown error"); + + (void) fclose(in); + (void) fclose(out); + (void) unlink(source); + return (nchars); + } + + (void) fclose(in); + (void) fclose(out); + (void) unlink(source); + rc = nchars; + } + + return (rc); +} /* Rename */ + +/* + * Function: dirname + * + * Arguments: char *FullPath + * + * Description: This function will return the directory name of the + * passed in filename. This is for out temporary file. + * the reason it is not in /tmp or /usr/tmp is that + * MV does not work across filesystems. + * + * Returns: char * + */ +static char * +dirname(char *FullPath) +{ + int len; + static char Dirname[MAX_FILENAME_LEN * 8]; + + (void) strncpy(Dirname, FullPath, MAX_FILENAME_LEN * 8); + Dirname[MAX_FILENAME_LEN * 8 - 1] = 0; + + for (len = strlen(Dirname); len; len--) { + if (Dirname[len] == '/') { + Dirname[len] = 0; + return (Dirname); + } + } + /* + * If we got here, then we searched the whole string, return NULL + */ + return (NULL); +} /* dirname */ + +/* + * Function: RemoveSection + * + * Arguments: int SectionNdx, IniFileType *File + * + * Description: This function will remove a section from the given INI file. + * It does all the necessary garbage collection. + * + * Returns: int (zero on success) + */ +static int +RemoveSection(int SectionNdx, IniFileType *File) +{ + /* First, remove all the labels */ + if (File->Sections[SectionNdx].Labels) + free(File->Sections[SectionNdx].Labels); + + /* Finally, remove the Section */ + if (File->NumSections && + (SectionNdx < File->NumSections) && + SectionNdx >= 0) { + int NumToMove; + NumToMove = File->NumSections - SectionNdx -1; + /* Copy the rest down a notch */ + if (NumToMove > 0) { + (void) memcpy(&File->Sections[SectionNdx], + &File->Sections[SectionNdx+1], + sizeof (SectionType) * NumToMove); + } + /* Free the last one */ + File->NumSections--; + return (0); + } /* Sanity Check */ + (void) snprintf(ErrorString, sizeof (ErrorString), + "Unable to remove section <%s> in INI file <%s>", + File->Sections->SectionName, File->Filename); + return (-1); +} /*RemoveSection*/ +/* + * Function: RemoveLabel + * + * Arguments: SectionType *Section, int LabelNdx + * + * Description: This function will remove a label from the given INI + * file. (No GC is necessary, since the Arrays are Static) + * + * Returns: int + */ +static int +RemoveLabel(SectionType *Section, int LabelNdx) +{ + + /* Sanity Check */ + if (Section->NumLabels && + (LabelNdx < Section->NumLabels) && + LabelNdx >= 0) { + int NumToMove; + NumToMove = Section->NumLabels - LabelNdx -1; + /* Copy the rest down a notch */ + if (NumToMove > 0) { + (void) memcpy(&Section->Labels[LabelNdx], + &Section->Labels[LabelNdx+1], + sizeof (LabelType) * NumToMove); + } + /* Free the last one */ + Section->NumLabels--; + return (0); + } /* Sanity Check */ + (void) snprintf(ErrorString, sizeof (ErrorString), + "Unable to remove label <%s> from INI file ", + Section->Labels->Label); + return (-1); +} /* RemoveLabel */ + +/* + * Function: IniUpdateLocalCopy + * + * Arguments: char *Filename, char *Section, char *Label, char *Data + * + * Description: This function will update the internal copy of the data + * we have. (It is called form IniUpdateFile) + * + * Returns: int + */ +static int +IniUpdateLocalCopy(char *Filename, char *Section, char *Label, char *Data) +{ + IniFileList *FileProbe; + IniFileType *File; + int SectionNdx, LabelNdx; + struct stat file_stats; + int DeleteSection = 0; + int DeleteLabel = 0; + int rc; + + /* Set our deletion flags */ + if (!Label && !Data) + DeleteSection = 1; + + if (!Data) + DeleteLabel = 1; + + /* + * First, search for the file + */ + for (FileProbe = IniHead; + FileProbe; + FileProbe = FileProbe->Next) { + if (strcmp(FileProbe->IniFile.Filename, + Filename) == 0) + break; + } + + if (!FileProbe) { + /* + * We did not find the file. Someone did a write without + * a read. Return an error. (The file is still written to, + * and the next read will parse it in.) + */ + (void) sprintf(ErrorString, "Warning: file not loaded."); + return (0); + } + File = &FileProbe->IniFile; + + /* + * Now let's update our statistics, so our cache is up to date. + */ + if (stat(Filename, &file_stats) == (-1)) { + char *errMsg = strerror(errno); + + (void) snprintf(ErrorString, sizeof (ErrorString), + "Error: Unable to retrieve statistics on <%s>. %s.", + Filename, errMsg != NULL ? errMsg : "Unknown error"); + + return (-2); + } else + File->ModificationTime = file_stats.st_mtime; + + /* + * now, File contains our file pointer. Check + * to see if our section exists. + */ + for (SectionNdx = 0; SectionNdx < File->NumSections; SectionNdx++) { + if (strcmp(Section, + File->Sections[SectionNdx].SectionName) == 0) { + /* We have the section! */ + break; + } + } + if (SectionNdx >= File->NumSections) { + if (DeleteSection || DeleteLabel) { + (void) snprintf(ErrorString, sizeof (ErrorString), + "Error IniUpdateLocalCopy: " + "Section not found in <%s>", + Filename); + return (-1); /* Error, not found */ + } + + /* Oops New Section/Label! */ + SectionNdx = AddSection(File, Section); + if (SectionNdx < 0) + return (SectionNdx); + (void) AddLabel(File, SectionNdx, Label, Data); + } else { + if (DeleteSection) { + return (RemoveSection(SectionNdx, File)); + } + /* We have the section. Search for the label */ + for (LabelNdx = 0; + LabelNdx < File->Sections[SectionNdx].NumLabels; + LabelNdx++) { + if (strcasecmp(Label, + File->Sections[SectionNdx].Labels[LabelNdx].Label) + == 0) { + if (DeleteLabel) { + return (RemoveLabel( + &File->Sections[SectionNdx], + LabelNdx)); + } + + /* Found the label. Update the data */ + ModifyLabel(File, SectionNdx, LabelNdx, Data); + break; + } + } + if (LabelNdx >= File->Sections[SectionNdx].NumLabels) { + if (DeleteLabel) { + (void) snprintf(ErrorString, + sizeof (ErrorString), + "Error IniUpdateLocalCopy: " + "Label not found in <%s>", + Filename); + return (-1); /* Error, not found */ + } + /* Need to add a label! */ + rc = AddLabel(File, SectionNdx, Label, Data); + if (rc < 0) + return (rc); + } + } + return (0); +} /* IniUpdateLocalCopy */ + +/* + * Function: AddSection + * + * Arguments: IniFileType *IniFile, char *Section + * + * Description: This function will add a section to the passed in file. + * + * Returns: int + */ +static int +AddSection(IniFileType *IniFile, char *Section) +{ + SectionType *SectionPointer; + + /* + * Set up new section Array + */ + SectionPointer = malloc(sizeof (SectionType) * + (IniFile->NumSections + 1)); + if (!SectionPointer) { + (void) strcpy(ErrorString, "Out of memory allocating section."); + return (-1); + } + /* + * Copy old sections over - including pointers + */ + if (IniFile->NumSections) { + (void) memcpy(SectionPointer, IniFile->Sections, + IniFile->NumSections * sizeof (SectionType)); + free(IniFile->Sections); /* Free the old sections Array */ + } + /* + * Update new section + */ + (void) memset(SectionPointer[IniFile->NumSections].SectionName, '0', + MAX_FILENAME_LEN); + (void) strncpy(SectionPointer[IniFile->NumSections].SectionName, + Section, + MAX_SECTION_LEN); + SectionPointer[ + IniFile->NumSections].SectionName[MAX_SECTION_LEN - 1] = 0; + SectionPointer[IniFile->NumSections].Labels = NULL; + SectionPointer[IniFile->NumSections].NumLabels = 0; + + IniFile->NumSections++; + IniFile->Sections = SectionPointer; /* Update array pointer */ + + /* Return an index to the newly added one */ + return (IniFile->NumSections-1); +} /* AddSection */ + +/* + * Function: AddLabel + * + * Arguments: IniFileType *IniFile, int SectionNdx, char *Label, char *Data + * + * Description: This function adds a label to a section. + * + * Returns: static int + */ +static int +AddLabel(IniFileType *IniFile, int SectionNdx, char *Label, char *Data) +{ + SectionType *SectionPointer; + LabelType *LabelPointer; + + /* + * Set up CurrentSection pointer for ease of typing. + */ + SectionPointer = &IniFile->Sections[SectionNdx]; + + /* + * Allocate enough room for new label + */ + LabelPointer = malloc(sizeof (LabelType) * + (SectionPointer->NumLabels+1)); + if (!LabelPointer) { + (void) strcpy(ErrorString, "Out of memory allocating label."); + return (-3); + } + if (SectionPointer->NumLabels) { + /* Do the copy */ + (void) memcpy(LabelPointer, SectionPointer->Labels, + sizeof (LabelType) * SectionPointer->NumLabels); + free(SectionPointer->Labels); + } + + (void) memset(LabelPointer[SectionPointer->NumLabels].Label, 0, + MAX_LABEL_LEN); + (void) memset(LabelPointer[SectionPointer->NumLabels].Value, 0, + MAX_VALUE_LEN); + (void) strlcpy(LabelPointer[SectionPointer->NumLabels].Label, + Label, MAX_LABEL_LEN); + (void) strlcpy(LabelPointer[SectionPointer->NumLabels].Value, + Data, MAX_VALUE_LEN); + + SectionPointer->NumLabels++; + SectionPointer->Labels = LabelPointer; + + /* return the index of the new label */ + return (SectionPointer->NumLabels-1); +} /* AddLabel */ + +/* + * Function: ModifyLabel + * + * Arguments: IniFileType *IniFile, int SectionNdx, int LabelNdx, char *Data + * + * Description: This function will just modify the data of a label in memory. + * + * Returns: void + */ +static void +ModifyLabel(IniFileType *IniFile, int SectionNdx, int LabelNdx, char *Data) +{ + (void) memset(IniFile->Sections[SectionNdx].Labels[LabelNdx].Value, + 0, MAX_VALUE_LEN); + (void) strlcpy(IniFile->Sections[SectionNdx].Labels[LabelNdx].Value, + Data, MAX_VALUE_LEN); +} /* ModifyLabel */ + +/* + * Function: SectionCmp + * + * Arguments: char *line, char *Section + * + * Description: This function returns zero if the line is a section line, + * and contains our section. + * + * Returns: int + */ +static int +SectionCmp(char *line, char *Section) +{ + char TempLabel[MAX_LABEL_LEN], TempValue[MAX_LABEL_LEN]; + + switch (ParseLine(line, TempLabel, TempValue)) { + case INI_SECTION: + return (strcmp(Section, TempLabel)); + default: /* Not a section */ + return (-1); + } + +} /* SectionCmp */ + +/* + * Function: CopyToSection + * + * Arguments: char *Section, FILE *in, FILE *out, int CopySection + * + * Description: Copies the files from in to out, until it gets to + * the namedSection. If CopySection is non-zero, it + * will also copy the section line. If it is zero + * the section line will not be copied (for deletion) + * + * Returns: int (non-zero if the section was found) + */ +static int +CopyToSection(char *Section, FILE *in, FILE *out, int CopySection) +{ + char tempbuffer[MAX_VALUE_LEN + MAX_LABEL_LEN]; + + while (fgets(tempbuffer, MAX_VALUE_LEN + MAX_LABEL_LEN, in)) { + if (!(SectionCmp(tempbuffer, Section))) { + /* We have the section */ + if (CopySection) + (void) fputs(tempbuffer, out); + + return (TRUE); + } + (void) fputs(tempbuffer, out); + } + + return (FALSE); +} /* CopyToSection */ + +/* + * Function: CopyToEOF + * + * Arguments: FILE *in, FILE *out, char *Label + * + * Description: Copies from *in to *out, deleting Label in the current + * section. If Lable is NULL, then all labels are deleted until + * the next section is reached. + * + * Returns: void + */ +static void +CopyToEOF(FILE *in, FILE *out, char *Label) +{ + char tempbuffer[BUF_LEN]; + int SectionFound = FALSE; + char TempLabel[MAX_LABEL_LEN]; + char TempValue[MAX_VALUE_LEN]; + + + while (fgets(tempbuffer, BUF_LEN - 1, in)) { + if (!SectionFound) { + switch (ParseLine(tempbuffer, TempLabel, TempValue)) { + case INI_SECTION: + (void) fputs(tempbuffer, out); + SectionFound = TRUE; + break; + case INI_LABEL: + if (Label) { + /* + * If label is non-null, then copy + * everything EXCEPT the given label. + */ + if (strcasecmp(Label, TempLabel)) { + (void) fputs(tempbuffer, out); + } + } + break; + default: + (void) fputs(tempbuffer, out); + break; + } + } else { + /* + * If the next section has been found, + * just write everything + */ + (void) fputs(tempbuffer, out); + } /* if SectionFound */ + } /* end While */ +} /* CopyToEOF */ + + +/* + * Function: GetSectionList + * + * Arguments: IniFileType *IniFile, char *argv, int *NumSections, + * int *elementSize + * + * Description: This routine returns a list of sections in a newly + * allocated array. + * + * Returns: char *, and modifies NumSections and elementSize + */ +static char * +GetSectionList(IniFileType *IniFile, char *argv, int *NumSections, + int *elementSize) +{ + int i; + + /* + * Do garbage collection + */ + if (argv) { + free(argv); + } + argv = NULL; + + if (!IniFile->NumSections) + return (argv); + + argv = calloc(1, IniFile->NumSections*MAX_FILENAME_LEN); + if (!argv) { + (void) sprintf(ErrorString, + "Out of memory getting section list."); + + return (NULL); + } + for (i = 0; i < IniFile->NumSections; i++) { + (void) strlcpy(&argv[i*MAX_FILENAME_LEN], + IniFile->Sections[i].SectionName, + MAX_FILENAME_LEN); + } + *NumSections = IniFile->NumSections; + *elementSize = MAX_FILENAME_LEN; + return (argv); +} /* GetSectionList */ + +/* + * Function: IniLoaded + * + * Arguments: char *Filename + * + * Description: Returns true if the specified file is loaded and has + * not changed. + * + * Returns: int + */ +static int +IniLoaded(char *Filename) +{ + IniFileList *Probe; + + for (Probe = IniHead; Probe; Probe = Probe->Next) { + if (strcmp(Filename, Probe->IniFile. Filename) == 0) { + if (FileHasChanged(Probe->IniFile.ModificationTime, + Filename)) { + return (FALSE); + } else { + return (TRUE); + } + } + } + return (FALSE); +} /* IniLoaded */ + + +/* + * Function: IniCheckComment + * + * Arguments: char *buffer + * + * Description: Returns true if the given line is a comment, or if it is + * blank. Also removes any partial-line comments by + * replacing the semi-colon with a NULL; + * + * A comment is of the form : + * ; comment + * or + * # comment + * + * Returns: int + */ +static int +IniCheckComment(char *buffer) +{ + int i; + + for (i = 0; buffer[i] && (buffer[i] != '\n'); i++) { + if (buffer[i] == ';' || buffer[i] == '#') { + if (i) { + /* check for \; or \# */ + if (buffer[i-1] == '\\') + continue; + } + /* + * Otherwise, mark it as a null, and check for an + * empty string + */ + buffer[i] = 0; + break; + } + } + + for (i = 0; buffer[i] && (buffer[i] != '\n'); i++) { + if (!isspace(buffer[i])) + return (0); + } + + return (1); /* This is a blank (or commented) line */ +} /* IniCheckComment */ + +/* + * Function: IniUnloadFile + * + * Arguments: char *Filename + * + * Description: This routine will remove an ini file from our list, + * and free up memory. + * + * Returns: int (zero on success) + */ +static int +IniUnloadFile(char *Filename) +{ + IniFileList *File; + + File = UnlinkFile(Filename); + if (!File) + return (-1); + IniFreeFile(File); + return (0); +} /* IniUnloadFile */ + +/* + * Function: IniFreeFile + * + * Arguments: IniFileList *File + * + * Description: Does the garbage collection on a file. (frees all data) + * + * Returns: void + */ +static void +IniFreeFile(IniFileList *File) +{ + int CurrentSection; + + /* + * Now, free up all the memory + */ + for (CurrentSection = 0; CurrentSection < File->IniFile.NumSections; + CurrentSection++) { + /* + * Free up label array + */ + if (File->IniFile.Sections[CurrentSection].Labels) + free(File->IniFile.Sections[CurrentSection].Labels); + } + + /* Now free up the sections */ + if (File->IniFile.Sections) + free(File->IniFile.Sections); + + /* and finally... */ + free(File); + +} /* IniFreeFile */ + +/* + * Function: UnlinkFile + * + * Arguments: char *Filename + * + * Description: This routine will remove the file from the linked list, and + * return a pointer to it, so it can be freed. + * + * Returns: IniFileList * + */ +static IniFileList * +UnlinkFile(char *Filename) +{ + IniFileList *Probe; + IniFileList *PrevProbe = NULL; + + for (Probe = IniHead; Probe; Probe = Probe->Next) { + if (strcmp(Filename, Probe->IniFile.Filename) == 0) { + if (!PrevProbe) { + IniHead = Probe->Next; + } else { + PrevProbe->Next = Probe->Next; + } + return (Probe); + } + PrevProbe = Probe; + } + return (NULL); +} /* UnlinkFile */ + +/* + * Function: GetSectionProfileString + * + * Arguments: char *Section, char *Label, dest, destLen + * + * Description: This function is part of GetPrivateProfileString. It was + * Only Added to improve the C-Style formatting. (Fors got + * nested too deep.) + * + * Returns: static int + */ +static int +GetSectionProfileString(IniFileList *IniFile, char *Section, char *Label, + char *dest, int destLen) +{ + int i; + + /* We have the file */ + for (i = 0; i < IniFile->IniFile.NumSections; i++) { + if (strcasecmp(Section, + IniFile->IniFile.Sections[i].SectionName) + == 0) { + return (GetLabelProfileString(IniFile, + i, Label, dest, destLen)); + } + } /* end section for */ + + (void) snprintf(ErrorString, sizeof (ErrorString), + "Unable to find section <%s>.", Section); + + return (-1); +} /* GetSectionProfileString */ + +/* + * Function: GetLabelProfileString + * + * Arguments: char *Section, char *Label, char *dest, int destLen + * + * Description: This function is part of GetPrivateProfileString. It was + * Only Added to improve the C-Style formatting. (Fors got + * nested too deep.) + * + * Returns: static int + */ +static int +GetLabelProfileString(IniFileList *IniFile, int si, char *Label, + char *dest, int destLen) +{ + int j; + + /* We have the section */ + for (j = 0; + j < IniFile->IniFile.Sections[si].NumLabels; + j++) { + if (strcasecmp(Label, + IniFile->IniFile.Sections[si].Labels[j].Label) == 0) { + /* We finally have it! */ + (void) strncpy(dest, + IniFile->IniFile.Sections[si].Labels[j].Value, + destLen); + return (0); + } + } /* end label for */ + + (void) snprintf(ErrorString, sizeof (ErrorString), + "Unable to find label <%s>.", Label); + + return (-1); +} /* GetLabelProfileString */ + +/* + * + * E X T E R N A L F U N C T I O N S + * + * These functions are called by external programs. (They are non-static) + * + */ + + + +/* + * Function: WritePrivateProfileString + * + * Arguments: char *Section, char *Label, char *data + * + * Description: Sets the new string into [Section] Label=data + * + * Returns: int (zero on success) + */ +int +WritePrivateProfileString(char *Section, char *Label, char *data, + char *Filename) +{ + /* + * Unload the file, if it is loaded. The next read will load it. + */ + + return (IniUpdateFile(Filename, Section, Label, data)); +} /* WritePrivateProfileString */ + +/* + * Function: DeletePrivateProfileSection + * + * Arguments: char *Section, char *Filename + * + * Description: Deletes an entire section (and all labels) + * + * Returns: int (zero on success) + */ +int +DeletePrivateProfileSection(char *Section, char *Filename) +{ + return (IniUpdateFile(Filename, Section, NULL, NULL)); +} /* DeletePrivateProfileSection*/ + +/* + * Function: DeletePrivateProfileLabel + * + * Arguments: char *Section, char *Label, char *Filename + * + * Description: Deletes a label from a section. + * + * Returns: int (zero on success) + */ +int +DeletePrivateProfileLabel(char *Section, char *Label, char *Filename) +{ + return (IniUpdateFile(Filename, Section, Label, NULL)); +} /* DeletePrivateProfileLabel */ + +/* + * Function: WritePrivateProfileInt + * + * Arguments: char *Section, char *Label, int data, char *Filename + * + * Description: Sets the new int into [Section] Label=data + * + * Returns: int (zero on success) + */ +int +WritePrivateProfileInt(char *Section, char *Label, int data, char *Filename) +{ + char Tempbuffer[MAX_LONG_LEN]; /* we only need 10 + a negative sign */ + + (void) sprintf(Tempbuffer, "%d", data); + return (IniUpdateFile(Filename, Section, Label, Tempbuffer)); +} /* WritePrivateProfileInt */ + +/* + * Function: GetPrivateProfileString + * + * Arguments: char *Section, char *Label, char *defaultValue + * + * Description: retrieves data from a section + * + * Returns: int (zero on success) + */ +int +GetPrivateProfileString(char *Section, char *Label, char *defaultValue, + char *dest, int destLen, char *Filename) +{ + IniFileList *IniFile; + char errMsg[ERROR_SUBSTRING_LEN]; + int rc; + + /* + * First, Lookup the file, then lookup the section, + * then lookup the label, then copy the string + */ + + ErrorString[0] = 0; /* Clear the error string */ + + /* set default value */ + (void) strlcpy(dest, defaultValue, destLen); + + if (!IniLoaded(Filename)) { + rc = IniLoadFile(Filename); + if (rc < 0) { + return (rc); + } + } + + for (IniFile = IniHead; IniFile; IniFile = IniFile->Next) { + if (strcmp(Filename, IniFile->IniFile.Filename) == 0) + return (GetSectionProfileString(IniFile, Section, + Label, dest, destLen)); + } /* end file for */ + + /* + * IniLoaded() and IniLoadFile() call FileHasChanged() which may have + * something to say via ErrorString - don't overwrite it! + */ + (void) snprintf(errMsg, ERROR_SUBSTRING_LEN, + "Unable to find file <%s>. ", Filename); + + strlcat(ErrorString, errMsg, sizeof (ErrorString)); + + return (-1); +} /* GetPrivateProfileString */ + +/* + * Function: GetPrivateProfileInt + * + * Arguments: char *Section, char *Label, int defaultValue + * + * Description: Returns the int associated with [Section], Label=Int + * + * Returns: int + */ +int +GetPrivateProfileInt(char *Section, char *Label, int defaultValue, + char *Filename) +{ + char String[MAX_LONG_LEN]; + + (void) GetPrivateProfileString(Section, Label, "", String, + MAX_LONG_LEN, Filename); + + if (!String[0]) /* Our default return value is "" */ + return (defaultValue); + else + return (atoi(String)); +} /* GetPrivateProfileInt */ + +/* + * Function: IniListSections + * + * Arguments: char *Filename, int *NumSections, int *elementSize + * + * Description: Returns a list of sections. (allocates an array) + * + * Returns: char * + */ +char * +IniListSections(char *Filename, int *NumSections, int *elementSize) +{ + static char *argv = NULL; + IniFileList *IniFile; + char errMsg[ERROR_SUBSTRING_LEN]; + int rc; + + if (!IniLoaded(Filename)) { + rc = IniLoadFile(Filename); + if (rc < 0) { + return (NULL); + } + } + for (IniFile = IniHead; IniFile; IniFile = IniFile->Next) { + if (strcmp(Filename, IniFile->IniFile.Filename) == 0) { + argv = GetSectionList(&IniFile->IniFile, argv, + NumSections, elementSize); + return (argv); + } + } + + /* + * IniLoaded() and IniLoadFile() call FileHasChanged() which may have + * something to say via ErrorString - don't overwrite it! + */ + (void) snprintf(errMsg, sizeof (ErrorString), + "Unable to find file <%s>. ", Filename); + + strlcat(ErrorString, errMsg, sizeof (ErrorString)); + + return (NULL); +} /* IniListSections */ + + +/* + * Function: parsealg + * + * Arguments: char *algname, struct ipsec_alg *table + * + * Description: finds the ipsec algorithm value associated with the ipsec + * algorithm string. + * + * Returns: valid alg value on success, -1 on failure. + */ +int +parsealg(char *algname, struct ipsec_alg *table) +{ + struct ipsec_alg *ep; + + if ((algname == NULL) || (table == NULL)) + return (-1); + + for (ep = table; ep->alg != NULL; ep++) { + if (strcasecmp(ep->alg, algname) == 0) + return (ep->value); + } + + /* no match */ + return (-1); +} + + +/* + * Function: parse_algs + * + * Arguments: int which_alg, int alg, ipsec_req_t *ipsr + * + * Description: sets the values in the ipsec_req_t passed in based on + * the algorithm, and which protection scheme it belongs to (ah_auth, + * esp_auth, or esp_encr. SA is also passed through here as a sanity + * check measure, and because of the way the parsing routines are + * designed - the user specifies all this as part of a the properties + * of a single IPsec policy. + * + * Returns: valid alg value on success, -1 on failure. + */ +int +parse_algs(int which_alg, int alg, ipsec_req_t *ipsr) +{ + if (alg == -1) + /* alg is bad */ + return (-1); + + if (ipsr == NULL) + /* user didn't pass a pointer to set, alg is valid, OK */ + return (0); + + switch (which_alg) { + case ESP_ENCR_ALG: + if (alg == NO_ESP_AALG) { + if (ipsr->ipsr_esp_auth_alg == SADB_AALG_NONE) + ipsr->ipsr_esp_req = 0; + ipsr->ipsr_esp_alg = SADB_EALG_NONE; + } else { + ipsr->ipsr_esp_req = + IPSEC_PREF_REQUIRED | IPSEC_PREF_UNIQUE; + ipsr->ipsr_esp_alg = alg; + } + break; + + case ESP_AUTH_ALG: + if (alg == NO_ESP_AALG) { + if (ipsr->ipsr_esp_alg == SADB_EALG_NONE || + ipsr->ipsr_esp_alg == SADB_EALG_NULL) + ipsr->ipsr_esp_req = 0; + ipsr->ipsr_esp_auth_alg = SADB_AALG_NONE; + } else { + ipsr->ipsr_esp_req = + IPSEC_PREF_REQUIRED | IPSEC_PREF_UNIQUE; + ipsr->ipsr_esp_auth_alg = alg; + + /* Let the user specify NULL encryption implicitly. */ + if (ipsr->ipsr_esp_alg == SADB_EALG_NONE && + !encr_alg_set) + ipsr->ipsr_esp_alg = SADB_EALG_NONE; + } + break; + + case AH_AUTH_ALG: + if (alg == NO_AH_AALG) { + ipsr->ipsr_ah_req = 0; + ipsr->ipsr_auth_alg = SADB_AALG_NONE; + } else { + ipsr->ipsr_ah_req = + IPSEC_PREF_REQUIRED | IPSEC_PREF_UNIQUE; + ipsr->ipsr_auth_alg = alg; + } + break; + + case SA_ALG: + if ((alg != SADB_SA_SHARED) && + (alg != SADB_SA_UNIQUE)) + return (-1); + break; + + default: + /* don't know what to do! Fail. */ + return (-1); + } + return (0); +} + +/* ipsec algorithm parsing routines */ +int +parse_esp_encr_alg(char *which_alg, ipsec_req_t *ipsr) +{ + return (parse_algs(ESP_ENCR_ALG, parsealg(which_alg, encr_algs), ipsr)); +} + +int +parse_esp_auth_alg(char *which_alg, ipsec_req_t *ipsr) +{ + return (parse_algs(ESP_AUTH_ALG, parsealg(which_alg, auth_algs), ipsr)); +} + +int +parse_ah_alg(char *which_alg, ipsec_req_t *ipsr) +{ + return (parse_algs(AH_AUTH_ALG, parsealg(which_alg, auth_algs), ipsr)); +} + +int +parse_sa_alg(char *which_alg, ipsec_req_t *ipsr) +{ + return (parse_algs(SA_ALG, parsealg(which_alg, sa_algs), ipsr)); +} + + +/* + * Function: isIPsecActionValid + * + * Parameters: action - the string containing the action in question. + * + * Description: Verifies the action is a valid ipsec action. Note that this + * function is NOT tollerant to leading whitespace! + * + * Returns: 0 on failure. + * strlen of the action on success (so the caller can index past it). + */ +uint_t +isIPsecActionValid(char *action) +{ + int i; + char *cp = action; + + for (i = 0; validIPsecAction[i] != NULL; i++) { + /* match check */ + if (strncasecmp(cp, validIPsecAction[i], + strlen(validIPsecAction[i])) == 0) + return (strlen(validIPsecAction[i])); + + /* try the next action */ + } + + return (0); +} + +/* + * Function: parseIPsecProps + * + * Parameters: props - the string containing "{<props>}" for validation. + * ipsr - place to put parsed policy, NULL if not required. + * In this case parseIPsecProps() just tests to see + * if props are valid. + * + * Description: Verify properties are valid, and if so, put their values + * in the struct ipsec_req_t passed in. Valid properties are + * of the form "<tag> <alg>". Supported <tags> are in ipseccmd[], + * and the corresponding algs are in auth_algs[], and encr_algs[]. + * Note: this function is tollerant to properties begining with + * blank spaces, but an open bracket MUST preceed <tag><alg>. + * + * Returns: 0 on failure in which case the values in ipsr are incomplete. + * number of bytes parsed on success in which case the values in ipsr, + * if passed in, are complete. + */ +int +parseIPsecProps(char *props, ipsec_req_t *ipsr) +{ + struct ipsec_cmd *cmd; + char *p, *freeP, *deltaP = 0, *lasts; + int bytes_parsed = 0, ioff = 0, ret; + boolean_t bopen_found = _B_FALSE, bclose_found = _B_FALSE; + + p = strdup(props); + + if (p == NULL) + return (0); + + freeP = p; /* strtok_r() is destructive */ + + while ((p = strtok_r(p, " ", &lasts)) != NULL) { + /* + * What did strtok_r() return if we have " { <properties..."? + * Skip white-space in general. ^^^ + */ + if ((*p != '\0') && (isspace(*p))) { + deltaP = p + strlen(p); + p = NULL; + continue; + } + + if (!bopen_found) { + /* Every property begins with an open-bracket */ + if (*p != '{') { + free(freeP); + return (0); + } + bopen_found = _B_TRUE; + /* move on */ + p++; + } + + if (*p == '}') { + /* this means we should be done */ + if ((!bopen_found) || (bclose_found)) { + free(freeP); + return (0); + } + + bclose_found = _B_TRUE; + + deltaP = p + strlen(p); + + p = NULL; + continue; + } + + if (bclose_found) { + /* Stuff after the close! */ + free(freeP); + return (0); + } + + /* once for each <tag> the user wants set */ + for (cmd = ipseccmd; cmd->c_func != NULL; cmd++) { + /* valid <tag>? */ + if ((cmd->c_name) && + (strcasecmp(cmd->c_name, p) == 0)) { + /* <alg> follows <tag>> */ + p = NULL; + p = strtok_r(p, " ", &lasts); + + if (p == NULL) { + /* nothing follows <tag> = error */ + free(freeP); + return (0); + } + + /* last <alg> may have a "}" at the end */ + if (strcmp(&p[strlen(p)-1], "}") == 0) { + if (bclose_found) { + /* already found one = fail */ + free(freeP); + return (0); + } + bclose_found = _B_TRUE; + + /* char shortcuts are cool */ + p[strlen(p)-1] = NULL; + ioff = 1; + } + + /* + * Call the parse command for this <alg>, but + * only if we're filling in the ipsec_req_t. + */ + if (ipsr == NULL) + /* make sure it's valid in context */ + ret = parsealg(p, encr_algs); + else + /* also parse it into ipsr */ + ret = (*cmd->c_func)(p, ipsr); + + if (ret < 0) { + /* the parse command failed */ + free(freeP); + return (0); + } else { + /* how far have we've come */ + deltaP = p + strlen(p) + ioff; + + /* parsed->next */ + p = NULL; + break; + } + } + } + + /* cmd->c_func = NULL, next alg */ + p = NULL; + } + + /* calculate how many bytes we've parsed */ + bytes_parsed = deltaP - freeP; + + /* finished with this */ + free(freeP); + + /* reset the per-policy parsing boolean */ + encr_alg_set = FALSE; + + /* as long as we got to a valid close bracket, we're fine */ + if (!bclose_found) + return (0); + + return (bytes_parsed); +} + +/* + * Function:isIPsecPolicyValid + * + * Arguments: policy what the user is trying to set as policy properties. + * + * Description: This function validates an IPSec policy. The policy MUST be + * a single valid action, followed by a valid set of properties + * as specified by ipsec(7P). Note that we don't necessarily + * support all the actions that ipsec supports, see + * validIPsecActions[]. + * + * Returns: _B_TRUE if the policy is valid, _B_FALSE if the policy is not. + * + * Note: this function only exists because ipSec has no API at this time. + */ +boolean_t +isIPsecPolicyValid(char *policy, ipsec_req_t *ipsr) +{ + int c_len = 0; + char *cp; + + if (policy == NULL) + return (_B_FALSE); + + /* Parse the policy */ + cp = policy; + + /* actions first */ + if ((c_len = isIPsecActionValid(cp)) == 0) + return (_B_FALSE); + + cp += c_len; + + while (isspace(*cp)) + cp++; + + /* now "{<properties>}" */ + if ((c_len = parseIPsecProps(cp, ipsr)) == 0) + return (_B_FALSE); + + cp += c_len; + + /* trailing blanks are OK... */ + while (isspace(*cp)) + cp++; + + /* ...but nothing else! */ + return (*cp == '\0'); +} diff --git a/deleted_files/usr/src/cmd/cmd-inet/common/conflib.h b/deleted_files/usr/src/cmd/cmd-inet/common/conflib.h new file mode 100644 index 0000000000..a6ad92e964 --- /dev/null +++ b/deleted_files/usr/src/cmd/cmd-inet/common/conflib.h @@ -0,0 +1,122 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _CONFLIB_H +#define _CONFLIB_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * conflib.h -- Prototypes and defines for conflib.c + * WARNING: This code assumes that an int is 32 bits. + */ + +#include <netinet/in.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Static lengths of values. */ +#define MAX_LABEL_LEN 256 +#define MAX_SECTION_LEN 256 +#define MAX_VALUE_LEN 256 +#define MAX_FILENAME_LEN 256 + +/* Error string readable by external programs */ +#define ERROR_SUBSTRING_LEN 256 +#define ERROR_STRING_LEN (MAX_FILENAME_LEN + ERROR_SUBSTRING_LEN) +extern char ErrorString[]; + +/* + * Check if OS has defined true or false. This code is portable between + * several OSs. + */ +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + + +/* these are shared between mipagent and mipagentconfig */ + +/* IPsec flags - what's in place to protect datagrams to/from an agent peer. */ +#define IPSEC_REQUEST_AH 0x01 /* regRequest using AH */ +#define IPSEC_REQUEST_ESP 0x02 /* regRequest using ESP */ +#define IPSEC_REPLY_AH 0x04 /* regReply using AH */ +#define IPSEC_REPLY_ESP 0x08 /* regReply using ESP */ +#define IPSEC_TUNNEL_AH 0x10 /* forward tunnel using AH */ +#define IPSEC_TUNNEL_ESP 0x20 /* forward tunnel using ESP */ +#define IPSEC_REVERSE_TUNNEL_AH 0x40 /* reverse tunnel using AH */ +#define IPSEC_REVERSE_TUNNEL_ESP 0x80 /* reverse tunnel using ESP */ + +/* useful combinations */ +#define IPSEC_REQUEST_BOTH (IPSEC_REQUEST_AH | IPSEC_REQUEST_ESP) +#define IPSEC_REPLY_BOTH (IPSEC_REPLY_AH | IPSEC_REPLY_ESP) +#define IPSEC_TUNNEL_BOTH (IPSEC_TUNNEL_AH | IPSEC_TUNNEL_ESP) +#define IPSEC_REVERSE_TUNNEL_BOTH \ + (IPSEC_REVERSE_TUNNEL_AH | IPSEC_REVERSE_TUNNEL_ESP) + +/* useful for checking if there's a policy that should be invoked */ +#define IPSEC_REQUEST_ANY(x) ((x) & (IPSEC_REQUEST_BOTH)) +#define IPSEC_REPLY_ANY(x) ((x) & (IPSEC_REPLY_BOTH)) +#define IPSEC_TUNNEL_ANY(x) ((x) & (IPSEC_TUNNEL_BOTH)) +#define IPSEC_REVERSE_TUNNEL_ANY(x) ((x) & (IPSEC_REVERSE_TUNNEL_BOTH)) + +/* useful for checking when user is requesting something that's not offered */ +#define IPSEC_ANY_AH(x) ((x) & (IPSEC_REQUEST_AH |\ + IPSEC_REPLY_AH |\ + IPSEC_TUNNEL_AH |\ + IPSEC_REVERSE_TUNNEL_AH)) + +#define IPSEC_ANY_ESP(x) ((x) & (IPSEC_REQUEST_ESP |\ + IPSEC_REPLY_ESP |\ + IPSEC_TUNNEL_ESP |\ + IPSEC_REVERSE_TUNNEL_ESP)) + +/* how policies are deliniated in CONF_FILE_NAME */ +#define IPSP_SEPARATOR ":" + +/* these functions are necessary to share IPsec functionality */ +int parseIPsecProps(char *, ipsec_req_t *); +boolean_t isIPsecPolicyValid(char *, ipsec_req_t *); + +/* These functions mimic the Windows(tm) equivilants */ +int WritePrivateProfileString(char *, char *, char *, char *); +int WritePrivateProfileInt(char *, char *, int, char *); +int GetPrivateProfileString(char *, char *, char *, char *, int, char *); +int GetPrivateProfileInt(char *, char *, int, char *); + +/* These functions were necessary for extra usability */ +char *IniListSections(char *, int *, int *); +int DeletePrivateProfileLabel(char *, char *, char *); +int DeletePrivateProfileSection(char *, char *); + +#ifdef __cplusplus +} +#endif + +#endif /* _CONFLIB_H */ |