[Autosec-devel] sonar/doc sonar_plugin_man.tex,NONE,1.1
Brought to you by:
red0x
From: red0x <re...@us...> - 2004-04-08 22:10:45
|
Update of /cvsroot/autosec/sonar/doc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22286 Added Files: sonar_plugin_man.tex Log Message: Added the plugin developer's manual --- NEW FILE: sonar_plugin_man.tex --- \documentclass[a4paper,10pt]{report} \usepackage{verbatim} % Title Page \title{Sonar Plugin Manual \\ 1.2.2} \author{Automated Security Tools} \begin{document} \maketitle \begin{abstract} This document exists to help you on your way to programming plugins for the \emph{sonar} network reconnaissance software. It will cover how to use the functions provided by sonar, what functions to provide, and how they must behave. Anyone interested in the debugging, developing, or understanding of sonar plugins should read this document. This paper will walk you through the development of a fully functional input plugin. Part I of the document gives the API specification, and part II walks through the development of a sample input plugin. \end{abstract} \tableofcontents \part{Plugin API Specification} \chapter{Plugin Functions} Depending on what type of plugin you are writing, you must specify certain required functions and fill them in. Input, Output, and Networking plugins have different requirements that we will outline below. Because of the structure of sonar's plugin API, you need not name your functions are they are named below, and in fact, I encourage you to choose a more descriptive name for your functions. However, you must provide a function that will perform the main task of the functions. Each plugin is assumed to return PLUGIN\_OK on success if it has an \emph{int} return type. \section{Input Plugins} \subsection{plugin\_open} \begin{verbatim} static int plugin_open(void *cmdline, int len); \end{verbatim} plugin\_open performs the following functions: \\ \begin{enumerate} \item Returns PLUGIN\_NOFILE on file not found errors. \item Marks your plugin as \emph{ready} if everything it is ready to begin giving input. \item If your plugin needs to open files or sockets, do that here. \item If everything preceeded without errors, return the size of the buffer you will be returning in plugin\_next. This step is crucially important. \item If you encountered errors, set \emph{errno} appropriately, and return PLUGIN\_ERROR \end{enumerate} \subsection{plugin\_next} \begin{verbatim} static int plugin_next(char *hostname); \end{verbatim} plugin\_next performs the following functions: \\ \begin{enumerate} \item Returns the next ip-address as a string pointed to by \emph{hostname}. \item Once the last hostname or ip-address has been returned, it should return PLUGIN\_EOF to signal that no more hostnames will follow. \item Any subsequent calls must result in the same error. \end{enumerate} \subsection{plugin\_close} \begin{verbatim} static int plugin_close(void); \end{verbatim} plugin\_close performs the following functions: \\ \begin{enumerate} \item Close any files or sockets opened in plugin\_open. \item Return the plugin to the state it was before plugin\_open was called. \item After this, a subsequent call to plugin\_open should \emph{not} return an error. \item Returns PLUGIN\_OK on success. \end{enumerate} \section{Output Plugins} \subsection{plugin\_output} \begin{verbatim} static int plugin_output(char *msg, va_list *ap); \end{verbatim} plugin\_output performs the following functions: \\ \begin{enumerate} \item Returns PLUGIN\_NOPEN if plugin is not marked as ready and selected. \item Returns PLUGIN\_NOFILE if the required output medium is not opened. It may provide some way to re-open it and mark it's errno accordingly. \item Print the msg and va-list using \emph{vfprintf(3)}. \end{enumerate} \subsection{plugin\_results} \begin{verbatim} static int plugin_results(target_t *result, unsigned int num); \end{verbatim} plugin\_results performs the following functions: \\ \begin{enumerate} \item Iterate over the linked list of results in \emph{result}. Assume there are \emph{num} entries, while still ensuring not to dereference \emph{NULL}. \item Output the contents of the target\_t structure in a way that makes sense for your output plugin. \item Ensure that each hostnames's port status, stats, and comments are printed out. \end{enumerate} \section{Network Plugins} \subsection{plugin\_sweep} \begin{verbatim} static int plugin_sweep(target_t *targets); \end{verbatim} plugin\_sweep performs the following functions: \begin{enumerate} \item Assume targets is a circularly linked list, and iterate over all the targets, performing the scan that your plugin provides. \item Return appropriate error codes in the plugin's \emph{errno} and/or by returning that value where appropriate. \item Return PLUGIN\_OK on success. \end{enumerate} \section{All Plugins} \subsection{plugin\_init} \begin{verbatim} void *plugin_init(void *in_data); \end{verbatim} Although you have freedom when naming other functions, a function named \emph{plugin\_init} \textbf{must} be defined in your plugin. This function will be called from sonar to load your plugin. If you plugin named it something else, it would not get loaded. \\ plugin\_init performs the following functions: \begin{enumerate} \item Obtain the \emph{sonar\_t} structure from the \emph{in\_data} pointer. \item Fill in a \emph{plugin\_t} structure with the relivant values and functions pointers for your plugin type. (See the plugin\_init guide below.) \item Set the plugin's \emph{errno} to \emph{PLUGIN\_LOADED} \end{enumerate} \subsubsection{Unnecessary function pointers} \paragraph{Input Plugins} Input plugins can leave the following function pointers in \emph{plugin\_t} defined to NULL: \begin{enumerate} \item plugin\_output \item plugin\_sweep \item plugin\_results \end{enumerate} \paragraph{Output Plugins} Output plugins can leave the following function pointers in \emph{plugin\_t} defined to NULL: \begin{enumerate} \item plugin\_next \item plugin\_sweep \end{enumerate} \paragraph{Network Plugins} Network plugins can leave the following function pointers in \emph{plugin\_t} defined to NULL: \begin{enumerate} \item plugin\_next \item plugin\_output \item plugin\_results \end{enumerate} \subsection{plugin\_destroy} \begin{verbatim} static int plugin_destroy(void); \end{verbatim} plugin\_destroy performs the following functions: \begin{enumerate} \item Fill the \emph{plugin\_t} structure with \emph{NULL} pointers for functions, and \emph{0} for variables. \item Set the plugin's \emph{errno} to \emph{PLUGIN\_UNLOADED} \item Perform any plugin specific file closing, memery freeing, etc. \end{enumerate} \subsection{plugin\_usage} \begin{verbatim} static void plugin_usage(void); \end{verbatim} plugin\_usage performs the following functions: \begin{enumerate} \item Print the usage using the \emph{output} function pointer stored in the plugin's \emph{sonar\_t} structure. \end{enumerate} \subsection{plugin\_status} \begin{verbatim} static void plugin_status(void); \end{verbatim} plugin\_status performs the following functions: \begin{enumerate} \item Print any relivant status information using the \emph{output} function as above. \end{enumerate} \subsection{plugin\_last\_error} \begin{verbatim} static int plugin_last_error(void); \end{verbatim} plugin\_last\_error performs the following functions: \begin{enumerate} \item Simply return the plugin's \emph{errno} value. \end{enumerate} \section{Guidlines to writing plugin\_init} In order to write a plugin\_init that functions the way it should, aim to remember these points: \begin{enumerate} \item Check that the \emph{in\_data argument} you are passed is not NULL. \item Check that the plugin api held in \emph{sonar\_t->api} is the correct number for your plugin. \item Set the appropriate plugin type in \emph{plugin\_t->type} and mark your plugin as \emph{not ready}. \item Set the appropriate function pointers. \item Set the appropriate identifying information as well. \item Finally, set the plugin's \emph{errno} to \emph{PLUGIN\_LOADED}. \end{enumerate} Beyond that, what you do with your plugin\_init function is up to you. \part{Writing Plugins: A Walkthrough} \chapter{Examples} For examples of working plugins, see the appropriate sources. \section{Sonar core plugins} For examples of sonar plugins, download the sonar core source code and look at the source code in the \emph{plugins} directory. These plugins are all fully functional, even though they may diviate a little from standard practice. They must use different style includes, because they must be built before the sonar header files are installed on the system. \section{Sonar plugins built separately} The autosec project provides a few example plugins that build outside of the source tree, and therefore are good starting places for your projects. They have two separate plugins available at the time of this writing. One is an extremely bare bones output plugin, and another is a working list input plugin, like the one we are going to develop in this paper. They are available in the Downloads section of \textbf{\emph{http://autosec.sf.net}} \section{Third Party plugins} Send me an email at \emph{red0x}@\emph{users.sourceforge.net} to let me know if you begin development of a third party plugin. Plugins need not be GPL'd, but any plugin that is not GPL'd cannot be distributed bundled with sonar, because it is GPL'd. Let me know if you have or have seen any third party plugins floating around. \chapter{Design Considerations} \section{Plugin Type} The first design decision you must make is what type of plugin do you want to create? The easiest types to make are input or output plugins. Networking plugins are harder, because they must handle all sorts of network communications. In this document, I will walk you through the creation of an input plugin that takes its input from a text file, one ip-address or hostname per line. \section{Purpose} Once you know your target plugin type, deciding your plugins purpose should be easy. For our input plugin, we will use it to parse a text file full of IP addresses and hostnames as targets. \section{Bare Bones} The next step, after you have written all this down, is the bare bones plugins source files. We will create \emph{bare.h} and \emph{bare.c} here. To begin, create a bare header file that looks something like this: \subsection{bare-1.h} \verbatiminput{example/bare-1.h} And create a bare bones \emph{bare.c} that looks like this: \subsection{bare-1.c} \verbatiminput{example/bare-1.c} These source files will be used as the bare bones to all your plugin development needs. \chapter{Source Code Development} Once you know your plugins intended functionality, it should be pretty easy to create a plugin to do what you want it to do. \section{bare.h modifications} \emph{bare.h} will, unfortunately, not cut it without modification for all your plugin needs. Since you, or anyone, may write plugins in C++ if desired, you must ensure that your \textbf{\emph{plugin\_init}} function is linked as a C function only, so we will create the needed additions to bare.h, and rename it to \textbf{sonar\_inp\_list.h} now: \subsection{sonar\_inp\_list-1.h} \verbatiminput{example/sonar_inp_list-1.h} \section{Header files} What all must be declared in the header file for your plugin? As a general rule of thumb, any structures local to your plugin, and datatypes that you will use frequently should go into the header file. You may, or may not, wrap the type declarations in the \emph{extern "C"} section, as you see fit. However, you \textbf{must} provide a \textbf{plugin\_init} function exactly as shown here: \begin{verbatim*} void *plugin_init(void *in_data); \end{verbatim*} Along with this definition, you should also include any other definitions and needed header files here. Our sonar\_inp\_list.h now looks like this: \subsection{sonar\_inp\_list-2.h} \verbatiminput{example/sonar_inp_list-2.h} \subsection{Notes} From here on, we will only show changes made to this file by showing what we add. You \textbf{must} include \textbf{\emph{sonar/plugin.h}} in your plugin's header file to access needed types and structures. \section{Source files} You may break your plugin into as many source files as you see fit. If your plugin is simple, and doesn't warrant too much modularization, that is fine. If it is complex, and needs lots of modularization, feel free. \subsection{Bare Bones} Your plugin must contain one function named \emph{plugin\_init} that will take a pointer to a \emph{sonar\_t} structure as an argument, and return a pointer to a \emph{plugin\_t} structure that is correctly filled in. Explanations on filling in this structure will follow. Other things your plugin must contain, are the required methods for each type of plugin. \subsection{plugin\_init} Your \emph{plugin\_init} function must initialize a \emph{plugin\_t} structure and return it. That is the only thing it \textbf{must} do, you may provide other functionality here. Do not print output in this function, please, instead, return one of the new error codes in \textbf{plugin.h} . An example of how to fill this structure in follows: \verbatiminput{example/sonar_inp_list-1.c} \subsubsection{File Managment} Since this plugin is an input plugin, we will need a file descriptor for the file we will read from. Add the following to the global declarations in your plugin: \begin{verbatim} static FILE *fp; \end{verbatim} And add the following line to the end of the \emph{plugin\_init} function: \begin{verbatim} fp = NULL; \end{verbatim} \subsection{plugin\_destroy} The next logical step in our development is to create a \emph{plugin\_destroy} function to cleanup when our plugin is done. We can add the following function to our plugin: \verbatiminput{example/sonar_inp_list-2.c} \subsection{plugin\_open} We need some way to get the filename from the user, and open our file before the plugin tries to read data, so we must develop our \emph{plugin\_open} function. My \emph{plugin\_open} checks for the file name on the command line. In order to get the argument to the plugin, you would run sonar like this: \begin{verbatim} bash# sonar -iL,<filename> ... \end{verbatim} Next, we must return the buffer size that sonar should expect to read from us. The finished function looks like this: \verbatiminput{example/sonar_inp_list-3.c} \subsection{plugin\_next} Now, we need some way to read our data, and return it to sonar. So, we will write \emph{plugin\_next} next. This function does the real important job of an input plugin. This function will read from the input file, and return the data to sonar. Since sonar will keep calling this function until it gets a \emph{PLUGIN\_EOF} or \emph{PLUGIN\_ERROR}, you must support such functionality accordingly. A \emph{while} loop performs this task nicely: \verbatiminput{example/sonar_inp_list-4.c} \subsection{plugin\_close} \emph{plugin\_close} is a relatively easy write. All we have to do is close our file, and set ourselves as not-ready. \verbatiminput{example/sonar_inp_list-5.c} \subsection{plugin\_usage and plugin\_status} Since both these functions are relatively easy writes, and perform similar user interaction, they will be written together. The \emph{plugin\_usage} function needs to accurately report to the user how to use your plugin. The \emph{plugin\_status} function needs to output the status of your plugin, being terse, while still reporting needed information. These functions are written as follows: \verbatiminput{example/sonar_inp_list-6.c} \subsection{plugin\_last\_error} This function only needs to return the plugin's \emph{errno}, like so: \verbatiminput{example/sonar_inp_list-7.c} \section{Finished} Now, you are finished writing a fully functional input plugin. The source to said plugin has been bundled with this guide so you may follow along. If your copy of the guide does not include the sonar\_inp\_list source, logon to http://autosec.sf.net and download a copy. \end{document} |