diff options
| author | Michael Biebl <biebl@debian.org> | 2010-11-29 00:47:11 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2010-11-29 00:47:11 +0100 |
| commit | 9fae01fa351805b2903e535736e06971bc0b925e (patch) | |
| tree | c19bccf84c9f894e50fae678ba6ee2b2044e2d30 /libnm-util | |
Imported Upstream version 0.8.1 upstream/0.8.1
Diffstat (limited to 'libnm-util')
66 files changed, 27046 insertions, 0 deletions
diff --git a/libnm-util/COPYING b/libnm-util/COPYING new file mode 100644 index 00000000..2ec1380e --- /dev/null +++ b/libnm-util/COPYING @@ -0,0 +1,488 @@ +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/libnm-util/Makefile.am b/libnm-util/Makefile.am new file mode 100644 index 00000000..ddc68408 --- /dev/null +++ b/libnm-util/Makefile.am @@ -0,0 +1,113 @@ +SUBDIRS=. tests + +INCLUDES = -I${top_srcdir} -I${top_srcdir}/include + +lib_LTLIBRARIES=libnm-util.la + +libnm_util_la_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(UUID_CFLAGS) \ + -DG_DISABLE_DEPRECATED + +libnm_util_include_HEADERS = \ + nm-connection.h \ + nm-setting.h \ + nm-setting-8021x.h \ + nm-setting-bluetooth.h \ + nm-setting-connection.h \ + nm-setting-ip4-config.h \ + nm-setting-ip6-config.h \ + nm-setting-ppp.h \ + nm-setting-pppoe.h \ + nm-setting-serial.h \ + nm-setting-gsm.h \ + nm-setting-cdma.h \ + nm-setting-olpc-mesh.h \ + nm-setting-wired.h \ + nm-setting-wireless.h \ + nm-setting-wireless-security.h \ + nm-setting-vpn.h \ + nm-utils.h + +libnm_util_la_SOURCES= \ + crypto.c \ + crypto.h \ + nm-connection.c \ + nm-param-spec-specialized.c \ + nm-param-spec-specialized.h \ + nm-setting.c \ + nm-setting-8021x.c \ + nm-setting-bluetooth.c \ + nm-setting-connection.c \ + nm-setting-ip4-config.c \ + nm-setting-ip6-config.c \ + nm-setting-ppp.c \ + nm-setting-pppoe.c \ + nm-setting-serial.c \ + nm-setting-gsm.c \ + nm-setting-cdma.c \ + nm-setting-olpc-mesh.c \ + nm-setting-wired.c \ + nm-setting-wireless.c \ + nm-setting-wireless-security.c \ + nm-setting-vpn.c \ + nm-utils.c \ + nm-utils-private.h \ + $(libnm_util_include_HEADERS) + +libnm_util_la_LIBADD = $(GLIB_LIBS) $(DBUS_LIBS) $(UUID_LIBS) + +libnm_util_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-util.ver \ + -version-info "4:4:3" + +if WITH_GNUTLS +libnm_util_la_SOURCES += crypto_gnutls.c +libnm_util_la_CPPFLAGS += $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS) +libnm_util_la_LIBADD += $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS) +endif + +if WITH_NSS +libnm_util_la_SOURCES += crypto_nss.c +libnm_util_la_CPPFLAGS += $(NSS_CFLAGS) +libnm_util_la_LIBADD += $(NSS_LIBS) +endif + +libnm_util_includedir=$(includedir)/NetworkManager + + +########################################### +# Crypto test library +########################################### + +noinst_LTLIBRARIES = libtest-crypto.la + +libtest_crypto_la_SOURCES = crypto.c + +libtest_crypto_la_CPPFLAGS = \ + $(GLIB_CFLAGS) + +libtest_crypto_la_LIBADD = \ + $(GLIB_LIBS) + +if WITH_GNUTLS +libtest_crypto_la_SOURCES += crypto_gnutls.c +libtest_crypto_la_CPPFLAGS += $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS) +libtest_crypto_la_LIBADD += $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS) +endif + +if WITH_NSS +libtest_crypto_la_SOURCES += crypto_nss.c +libtest_crypto_la_CPPFLAGS += $(NSS_CFLAGS) +libtest_crypto_la_LIBADD += $(NSS_LIBS) +endif + + + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libnm-util.pc + +DISTCLEANFILES = libnm-util.pc + +EXTRA_DIST = libnm-util.pc.in libnm-util.ver + diff --git a/libnm-util/Makefile.in b/libnm-util/Makefile.in new file mode 100644 index 00000000..2da64da9 --- /dev/null +++ b/libnm-util/Makefile.in @@ -0,0 +1,1121 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@WITH_GNUTLS_TRUE@am__append_1 = crypto_gnutls.c +@WITH_GNUTLS_TRUE@am__append_2 = $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS) +@WITH_GNUTLS_TRUE@am__append_3 = $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS) +@WITH_NSS_TRUE@am__append_4 = crypto_nss.c +@WITH_NSS_TRUE@am__append_5 = $(NSS_CFLAGS) +@WITH_NSS_TRUE@am__append_6 = $(NSS_LIBS) +@WITH_GNUTLS_TRUE@am__append_7 = crypto_gnutls.c +@WITH_GNUTLS_TRUE@am__append_8 = $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS) +@WITH_GNUTLS_TRUE@am__append_9 = $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS) +@WITH_NSS_TRUE@am__append_10 = crypto_nss.c +@WITH_NSS_TRUE@am__append_11 = $(NSS_CFLAGS) +@WITH_NSS_TRUE@am__append_12 = $(NSS_LIBS) +subdir = libnm-util +DIST_COMMON = $(libnm_util_include_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/libnm-util.pc.in COPYING +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = libnm-util.pc +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(libnm_util_includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +@WITH_GNUTLS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@WITH_GNUTLS_TRUE@ $(am__DEPENDENCIES_1) +@WITH_NSS_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) +libnm_util_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) +am__libnm_util_la_SOURCES_DIST = crypto.c crypto.h nm-connection.c \ + nm-param-spec-specialized.c nm-param-spec-specialized.h \ + nm-setting.c nm-setting-8021x.c nm-setting-bluetooth.c \ + nm-setting-connection.c nm-setting-ip4-config.c \ + nm-setting-ip6-config.c nm-setting-ppp.c nm-setting-pppoe.c \ + nm-setting-serial.c nm-setting-gsm.c nm-setting-cdma.c \ + nm-setting-olpc-mesh.c nm-setting-wired.c \ + nm-setting-wireless.c nm-setting-wireless-security.c \ + nm-setting-vpn.c nm-utils.c nm-utils-private.h nm-connection.h \ + nm-setting.h nm-setting-8021x.h nm-setting-bluetooth.h \ + nm-setting-connection.h nm-setting-ip4-config.h \ + nm-setting-ip6-config.h nm-setting-ppp.h nm-setting-pppoe.h \ + nm-setting-serial.h nm-setting-gsm.h nm-setting-cdma.h \ + nm-setting-olpc-mesh.h nm-setting-wired.h \ + nm-setting-wireless.h nm-setting-wireless-security.h \ + nm-setting-vpn.h nm-utils.h crypto_gnutls.c crypto_nss.c +am__objects_1 = +@WITH_GNUTLS_TRUE@am__objects_2 = libnm_util_la-crypto_gnutls.lo +@WITH_NSS_TRUE@am__objects_3 = libnm_util_la-crypto_nss.lo +am_libnm_util_la_OBJECTS = libnm_util_la-crypto.lo \ + libnm_util_la-nm-connection.lo \ + libnm_util_la-nm-param-spec-specialized.lo \ + libnm_util_la-nm-setting.lo libnm_util_la-nm-setting-8021x.lo \ + libnm_util_la-nm-setting-bluetooth.lo \ + libnm_util_la-nm-setting-connection.lo \ + libnm_util_la-nm-setting-ip4-config.lo \ + libnm_util_la-nm-setting-ip6-config.lo \ + libnm_util_la-nm-setting-ppp.lo \ + libnm_util_la-nm-setting-pppoe.lo \ + libnm_util_la-nm-setting-serial.lo \ + libnm_util_la-nm-setting-gsm.lo \ + libnm_util_la-nm-setting-cdma.lo \ + libnm_util_la-nm-setting-olpc-mesh.lo \ + libnm_util_la-nm-setting-wired.lo \ + libnm_util_la-nm-setting-wireless.lo \ + libnm_util_la-nm-setting-wireless-security.lo \ + libnm_util_la-nm-setting-vpn.lo libnm_util_la-nm-utils.lo \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) +libnm_util_la_OBJECTS = $(am_libnm_util_la_OBJECTS) +libnm_util_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libnm_util_la_LDFLAGS) $(LDFLAGS) -o $@ +libtest_crypto_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) +am__libtest_crypto_la_SOURCES_DIST = crypto.c crypto_gnutls.c \ + crypto_nss.c +@WITH_GNUTLS_TRUE@am__objects_4 = libtest_crypto_la-crypto_gnutls.lo +@WITH_NSS_TRUE@am__objects_5 = libtest_crypto_la-crypto_nss.lo +am_libtest_crypto_la_OBJECTS = libtest_crypto_la-crypto.lo \ + $(am__objects_4) $(am__objects_5) +libtest_crypto_la_OBJECTS = $(am_libtest_crypto_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libnm_util_la_SOURCES) $(libtest_crypto_la_SOURCES) +DIST_SOURCES = $(am__libnm_util_la_SOURCES_DIST) \ + $(am__libtest_crypto_la_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +DATA = $(pkgconfig_DATA) +HEADERS = $(libnm_util_include_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISABLE_DEPRECATED = @DISABLE_DEPRECATED@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GMODULE_CFLAGS = @GMODULE_CFLAGS@ +GMODULE_LIBS = @GMODULE_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +IPTABLES_PATH = @IPTABLES_PATH@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBM = @LIBM@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POFILES = @POFILES@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +RANLIB = @RANLIB@ +RESOLVCONF_PATH = @RESOLVCONF_PATH@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = . tests +INCLUDES = -I${top_srcdir} -I${top_srcdir}/include +lib_LTLIBRARIES = libnm-util.la +libnm_util_la_CPPFLAGS = $(GLIB_CFLAGS) $(DBUS_CFLAGS) $(UUID_CFLAGS) \ + -DG_DISABLE_DEPRECATED $(am__append_2) $(am__append_5) +libnm_util_include_HEADERS = \ + nm-connection.h \ + nm-setting.h \ + nm-setting-8021x.h \ + nm-setting-bluetooth.h \ + nm-setting-connection.h \ + nm-setting-ip4-config.h \ + nm-setting-ip6-config.h \ + nm-setting-ppp.h \ + nm-setting-pppoe.h \ + nm-setting-serial.h \ + nm-setting-gsm.h \ + nm-setting-cdma.h \ + nm-setting-olpc-mesh.h \ + nm-setting-wired.h \ + nm-setting-wireless.h \ + nm-setting-wireless-security.h \ + nm-setting-vpn.h \ + nm-utils.h + +libnm_util_la_SOURCES = crypto.c crypto.h nm-connection.c \ + nm-param-spec-specialized.c nm-param-spec-specialized.h \ + nm-setting.c nm-setting-8021x.c nm-setting-bluetooth.c \ + nm-setting-connection.c nm-setting-ip4-config.c \ + nm-setting-ip6-config.c nm-setting-ppp.c nm-setting-pppoe.c \ + nm-setting-serial.c nm-setting-gsm.c nm-setting-cdma.c \ + nm-setting-olpc-mesh.c nm-setting-wired.c \ + nm-setting-wireless.c nm-setting-wireless-security.c \ + nm-setting-vpn.c nm-utils.c nm-utils-private.h \ + $(libnm_util_include_HEADERS) $(am__append_1) $(am__append_4) +libnm_util_la_LIBADD = $(GLIB_LIBS) $(DBUS_LIBS) $(UUID_LIBS) \ + $(am__append_3) $(am__append_6) +libnm_util_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-util.ver \ + -version-info "4:4:3" + +libnm_util_includedir = $(includedir)/NetworkManager + +########################################### +# Crypto test library +########################################### +noinst_LTLIBRARIES = libtest-crypto.la +libtest_crypto_la_SOURCES = crypto.c $(am__append_7) $(am__append_10) +libtest_crypto_la_CPPFLAGS = $(GLIB_CFLAGS) $(am__append_8) \ + $(am__append_11) +libtest_crypto_la_LIBADD = $(GLIB_LIBS) $(am__append_9) \ + $(am__append_12) +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libnm-util.pc +DISTCLEANFILES = libnm-util.pc +EXTRA_DIST = libnm-util.pc.in libnm-util.ver +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libnm-util/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libnm-util/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +libnm-util.pc: $(top_builddir)/config.status $(srcdir)/libnm-util.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libnm-util.la: $(libnm_util_la_OBJECTS) $(libnm_util_la_DEPENDENCIES) + $(libnm_util_la_LINK) -rpath $(libdir) $(libnm_util_la_OBJECTS) $(libnm_util_la_LIBADD) $(LIBS) +libtest-crypto.la: $(libtest_crypto_la_OBJECTS) $(libtest_crypto_la_DEPENDENCIES) + $(LINK) $(libtest_crypto_la_OBJECTS) $(libtest_crypto_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-crypto.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-crypto_gnutls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-crypto_nss.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-param-spec-specialized.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-8021x.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-bluetooth.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-cdma.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-gsm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-ip4-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-ip6-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-olpc-mesh.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-ppp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-pppoe.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-serial.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-vpn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-wired.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-wireless-security.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-wireless.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-utils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_crypto_la-crypto.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_crypto_la-crypto_gnutls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_crypto_la-crypto_nss.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libnm_util_la-crypto.lo: crypto.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-crypto.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-crypto.Tpo -c -o libnm_util_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-crypto.Tpo $(DEPDIR)/libnm_util_la-crypto.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto.c' object='libnm_util_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c + +libnm_util_la-nm-connection.lo: nm-connection.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-connection.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-connection.Tpo -c -o libnm_util_la-nm-connection.lo `test -f 'nm-connection.c' || echo '$(srcdir)/'`nm-connection.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-connection.Tpo $(DEPDIR)/libnm_util_la-nm-connection.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-connection.c' object='libnm_util_la-nm-connection.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-connection.lo `test -f 'nm-connection.c' || echo '$(srcdir)/'`nm-connection.c + +libnm_util_la-nm-param-spec-specialized.lo: nm-param-spec-specialized.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-param-spec-specialized.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-param-spec-specialized.Tpo -c -o libnm_util_la-nm-param-spec-specialized.lo `test -f 'nm-param-spec-specialized.c' || echo '$(srcdir)/'`nm-param-spec-specialized.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-param-spec-specialized.Tpo $(DEPDIR)/libnm_util_la-nm-param-spec-specialized.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-param-spec-specialized.c' object='libnm_util_la-nm-param-spec-specialized.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-param-spec-specialized.lo `test -f 'nm-param-spec-specialized.c' || echo '$(srcdir)/'`nm-param-spec-specialized.c + +libnm_util_la-nm-setting.lo: nm-setting.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting.Tpo -c -o libnm_util_la-nm-setting.lo `test -f 'nm-setting.c' || echo '$(srcdir)/'`nm-setting.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting.Tpo $(DEPDIR)/libnm_util_la-nm-setting.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting.c' object='libnm_util_la-nm-setting.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting.lo `test -f 'nm-setting.c' || echo '$(srcdir)/'`nm-setting.c + +libnm_util_la-nm-setting-8021x.lo: nm-setting-8021x.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-8021x.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-8021x.Tpo -c -o libnm_util_la-nm-setting-8021x.lo `test -f 'nm-setting-8021x.c' || echo '$(srcdir)/'`nm-setting-8021x.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-8021x.Tpo $(DEPDIR)/libnm_util_la-nm-setting-8021x.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-8021x.c' object='libnm_util_la-nm-setting-8021x.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-8021x.lo `test -f 'nm-setting-8021x.c' || echo '$(srcdir)/'`nm-setting-8021x.c + +libnm_util_la-nm-setting-bluetooth.lo: nm-setting-bluetooth.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-bluetooth.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-bluetooth.Tpo -c -o libnm_util_la-nm-setting-bluetooth.lo `test -f 'nm-setting-bluetooth.c' || echo '$(srcdir)/'`nm-setting-bluetooth.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-bluetooth.Tpo $(DEPDIR)/libnm_util_la-nm-setting-bluetooth.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-bluetooth.c' object='libnm_util_la-nm-setting-bluetooth.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-bluetooth.lo `test -f 'nm-setting-bluetooth.c' || echo '$(srcdir)/'`nm-setting-bluetooth.c + +libnm_util_la-nm-setting-connection.lo: nm-setting-connection.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-connection.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-connection.Tpo -c -o libnm_util_la-nm-setting-connection.lo `test -f 'nm-setting-connection.c' || echo '$(srcdir)/'`nm-setting-connection.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-connection.Tpo $(DEPDIR)/libnm_util_la-nm-setting-connection.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-connection.c' object='libnm_util_la-nm-setting-connection.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-connection.lo `test -f 'nm-setting-connection.c' || echo '$(srcdir)/'`nm-setting-connection.c + +libnm_util_la-nm-setting-ip4-config.lo: nm-setting-ip4-config.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-ip4-config.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-ip4-config.Tpo -c -o libnm_util_la-nm-setting-ip4-config.lo `test -f 'nm-setting-ip4-config.c' || echo '$(srcdir)/'`nm-setting-ip4-config.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-ip4-config.Tpo $(DEPDIR)/libnm_util_la-nm-setting-ip4-config.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-ip4-config.c' object='libnm_util_la-nm-setting-ip4-config.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-ip4-config.lo `test -f 'nm-setting-ip4-config.c' || echo '$(srcdir)/'`nm-setting-ip4-config.c + +libnm_util_la-nm-setting-ip6-config.lo: nm-setting-ip6-config.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-ip6-config.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-ip6-config.Tpo -c -o libnm_util_la-nm-setting-ip6-config.lo `test -f 'nm-setting-ip6-config.c' || echo '$(srcdir)/'`nm-setting-ip6-config.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-ip6-config.Tpo $(DEPDIR)/libnm_util_la-nm-setting-ip6-config.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-ip6-config.c' object='libnm_util_la-nm-setting-ip6-config.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-ip6-config.lo `test -f 'nm-setting-ip6-config.c' || echo '$(srcdir)/'`nm-setting-ip6-config.c + +libnm_util_la-nm-setting-ppp.lo: nm-setting-ppp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-ppp.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-ppp.Tpo -c -o libnm_util_la-nm-setting-ppp.lo `test -f 'nm-setting-ppp.c' || echo '$(srcdir)/'`nm-setting-ppp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-ppp.Tpo $(DEPDIR)/libnm_util_la-nm-setting-ppp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-ppp.c' object='libnm_util_la-nm-setting-ppp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-ppp.lo `test -f 'nm-setting-ppp.c' || echo '$(srcdir)/'`nm-setting-ppp.c + +libnm_util_la-nm-setting-pppoe.lo: nm-setting-pppoe.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-pppoe.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-pppoe.Tpo -c -o libnm_util_la-nm-setting-pppoe.lo `test -f 'nm-setting-pppoe.c' || echo '$(srcdir)/'`nm-setting-pppoe.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-pppoe.Tpo $(DEPDIR)/libnm_util_la-nm-setting-pppoe.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-pppoe.c' object='libnm_util_la-nm-setting-pppoe.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-pppoe.lo `test -f 'nm-setting-pppoe.c' || echo '$(srcdir)/'`nm-setting-pppoe.c + +libnm_util_la-nm-setting-serial.lo: nm-setting-serial.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-serial.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-serial.Tpo -c -o libnm_util_la-nm-setting-serial.lo `test -f 'nm-setting-serial.c' || echo '$(srcdir)/'`nm-setting-serial.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-serial.Tpo $(DEPDIR)/libnm_util_la-nm-setting-serial.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-serial.c' object='libnm_util_la-nm-setting-serial.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-serial.lo `test -f 'nm-setting-serial.c' || echo '$(srcdir)/'`nm-setting-serial.c + +libnm_util_la-nm-setting-gsm.lo: nm-setting-gsm.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-gsm.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-gsm.Tpo -c -o libnm_util_la-nm-setting-gsm.lo `test -f 'nm-setting-gsm.c' || echo '$(srcdir)/'`nm-setting-gsm.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-gsm.Tpo $(DEPDIR)/libnm_util_la-nm-setting-gsm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-gsm.c' object='libnm_util_la-nm-setting-gsm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-gsm.lo `test -f 'nm-setting-gsm.c' || echo '$(srcdir)/'`nm-setting-gsm.c + +libnm_util_la-nm-setting-cdma.lo: nm-setting-cdma.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-cdma.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-cdma.Tpo -c -o libnm_util_la-nm-setting-cdma.lo `test -f 'nm-setting-cdma.c' || echo '$(srcdir)/'`nm-setting-cdma.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-cdma.Tpo $(DEPDIR)/libnm_util_la-nm-setting-cdma.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-cdma.c' object='libnm_util_la-nm-setting-cdma.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-cdma.lo `test -f 'nm-setting-cdma.c' || echo '$(srcdir)/'`nm-setting-cdma.c + +libnm_util_la-nm-setting-olpc-mesh.lo: nm-setting-olpc-mesh.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-olpc-mesh.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-olpc-mesh.Tpo -c -o libnm_util_la-nm-setting-olpc-mesh.lo `test -f 'nm-setting-olpc-mesh.c' || echo '$(srcdir)/'`nm-setting-olpc-mesh.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-olpc-mesh.Tpo $(DEPDIR)/libnm_util_la-nm-setting-olpc-mesh.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-olpc-mesh.c' object='libnm_util_la-nm-setting-olpc-mesh.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-olpc-mesh.lo `test -f 'nm-setting-olpc-mesh.c' || echo '$(srcdir)/'`nm-setting-olpc-mesh.c + +libnm_util_la-nm-setting-wired.lo: nm-setting-wired.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-wired.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-wired.Tpo -c -o libnm_util_la-nm-setting-wired.lo `test -f 'nm-setting-wired.c' || echo '$(srcdir)/'`nm-setting-wired.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-wired.Tpo $(DEPDIR)/libnm_util_la-nm-setting-wired.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-wired.c' object='libnm_util_la-nm-setting-wired.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-wired.lo `test -f 'nm-setting-wired.c' || echo '$(srcdir)/'`nm-setting-wired.c + +libnm_util_la-nm-setting-wireless.lo: nm-setting-wireless.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-wireless.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-wireless.Tpo -c -o libnm_util_la-nm-setting-wireless.lo `test -f 'nm-setting-wireless.c' || echo '$(srcdir)/'`nm-setting-wireless.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-wireless.Tpo $(DEPDIR)/libnm_util_la-nm-setting-wireless.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-wireless.c' object='libnm_util_la-nm-setting-wireless.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-wireless.lo `test -f 'nm-setting-wireless.c' || echo '$(srcdir)/'`nm-setting-wireless.c + +libnm_util_la-nm-setting-wireless-security.lo: nm-setting-wireless-security.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-wireless-security.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-wireless-security.Tpo -c -o libnm_util_la-nm-setting-wireless-security.lo `test -f 'nm-setting-wireless-security.c' || echo '$(srcdir)/'`nm-setting-wireless-security.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-wireless-security.Tpo $(DEPDIR)/libnm_util_la-nm-setting-wireless-security.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-wireless-security.c' object='libnm_util_la-nm-setting-wireless-security.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-wireless-security.lo `test -f 'nm-setting-wireless-security.c' || echo '$(srcdir)/'`nm-setting-wireless-security.c + +libnm_util_la-nm-setting-vpn.lo: nm-setting-vpn.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-vpn.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-vpn.Tpo -c -o libnm_util_la-nm-setting-vpn.lo `test -f 'nm-setting-vpn.c' || echo '$(srcdir)/'`nm-setting-vpn.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-vpn.Tpo $(DEPDIR)/libnm_util_la-nm-setting-vpn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-setting-vpn.c' object='libnm_util_la-nm-setting-vpn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-vpn.lo `test -f 'nm-setting-vpn.c' || echo '$(srcdir)/'`nm-setting-vpn.c + +libnm_util_la-nm-utils.lo: nm-utils.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-utils.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-utils.Tpo -c -o libnm_util_la-nm-utils.lo `test -f 'nm-utils.c' || echo '$(srcdir)/'`nm-utils.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-nm-utils.Tpo $(DEPDIR)/libnm_util_la-nm-utils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-utils.c' object='libnm_util_la-nm-utils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-utils.lo `test -f 'nm-utils.c' || echo '$(srcdir)/'`nm-utils.c + +libnm_util_la-crypto_gnutls.lo: crypto_gnutls.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-crypto_gnutls.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-crypto_gnutls.Tpo -c -o libnm_util_la-crypto_gnutls.lo `test -f 'crypto_gnutls.c' || echo '$(srcdir)/'`crypto_gnutls.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-crypto_gnutls.Tpo $(DEPDIR)/libnm_util_la-crypto_gnutls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto_gnutls.c' object='libnm_util_la-crypto_gnutls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-crypto_gnutls.lo `test -f 'crypto_gnutls.c' || echo '$(srcdir)/'`crypto_gnutls.c + +libnm_util_la-crypto_nss.lo: crypto_nss.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-crypto_nss.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-crypto_nss.Tpo -c -o libnm_util_la-crypto_nss.lo `test -f 'crypto_nss.c' || echo '$(srcdir)/'`crypto_nss.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnm_util_la-crypto_nss.Tpo $(DEPDIR)/libnm_util_la-crypto_nss.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto_nss.c' object='libnm_util_la-crypto_nss.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-crypto_nss.lo `test -f 'crypto_nss.c' || echo '$(srcdir)/'`crypto_nss.c + +libtest_crypto_la-crypto.lo: crypto.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_crypto_la-crypto.lo -MD -MP -MF $(DEPDIR)/libtest_crypto_la-crypto.Tpo -c -o libtest_crypto_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libtest_crypto_la-crypto.Tpo $(DEPDIR)/libtest_crypto_la-crypto.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto.c' object='libtest_crypto_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_crypto_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c + +libtest_crypto_la-crypto_gnutls.lo: crypto_gnutls.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_crypto_la-crypto_gnutls.lo -MD -MP -MF $(DEPDIR)/libtest_crypto_la-crypto_gnutls.Tpo -c -o libtest_crypto_la-crypto_gnutls.lo `test -f 'crypto_gnutls.c' || echo '$(srcdir)/'`crypto_gnutls.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libtest_crypto_la-crypto_gnutls.Tpo $(DEPDIR)/libtest_crypto_la-crypto_gnutls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto_gnutls.c' object='libtest_crypto_la-crypto_gnutls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_crypto_la-crypto_gnutls.lo `test -f 'crypto_gnutls.c' || echo '$(srcdir)/'`crypto_gnutls.c + +libtest_crypto_la-crypto_nss.lo: crypto_nss.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_crypto_la-crypto_nss.lo -MD -MP -MF $(DEPDIR)/libtest_crypto_la-crypto_nss.Tpo -c -o libtest_crypto_la-crypto_nss.lo `test -f 'crypto_nss.c' || echo '$(srcdir)/'`crypto_nss.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libtest_crypto_la-crypto_nss.Tpo $(DEPDIR)/libtest_crypto_la-crypto_nss.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto_nss.c' object='libtest_crypto_la-crypto_nss.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_crypto_la-crypto_nss.lo `test -f 'crypto_nss.c' || echo '$(srcdir)/'`crypto_nss.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files +install-libnm_util_includeHEADERS: $(libnm_util_include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(libnm_util_includedir)" || $(MKDIR_P) "$(DESTDIR)$(libnm_util_includedir)" + @list='$(libnm_util_include_HEADERS)'; test -n "$(libnm_util_includedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnm_util_includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnm_util_includedir)" || exit $$?; \ + done + +uninstall-libnm_util_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnm_util_include_HEADERS)'; test -n "$(libnm_util_includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libnm_util_includedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libnm_util_includedir)" && rm -f $$files + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(libnm_util_includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstLTLIBRARIES mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-libnm_util_includeHEADERS \ + install-pkgconfigDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES \ + uninstall-libnm_util_includeHEADERS uninstall-pkgconfigDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ + ctags ctags-recursive distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-libnm_util_includeHEADERS install-man install-pdf \ + install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-libLTLIBRARIES \ + uninstall-libnm_util_includeHEADERS uninstall-pkgconfigDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libnm-util/crypto.c b/libnm-util/crypto.c new file mode 100644 index 00000000..813cbc8e --- /dev/null +++ b/libnm-util/crypto.c @@ -0,0 +1,636 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2009 Red Hat, Inc. + */ + +#include <glib.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <glib/gi18n.h> + +#include "crypto.h" + +GQuark +_nm_crypto_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-crypto-error-quark"); + return quark; +} + + +static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; +static const char *pem_rsa_key_end = "-----END RSA PRIVATE KEY-----"; + +static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----"; +static const char *pem_dsa_key_end = "-----END DSA PRIVATE KEY-----"; + +static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----"; +static const char *pem_cert_end = "-----END CERTIFICATE-----"; + +static const char * +find_tag (const char *tag, const char *buf, gsize len) +{ + gsize i, taglen; + + taglen = strlen (tag); + if (len < taglen) + return NULL; + + for (i = 0; i < len - taglen + 1; i++) { + if (memcmp (buf + i, tag, taglen) == 0) + return buf + i; + } + return NULL; +} + +#define DEK_INFO_TAG "DEK-Info: " +#define PROC_TYPE_TAG "Proc-Type: " + +static GByteArray * +parse_old_openssl_key_file (GByteArray *contents, + int key_type, + char **out_cipher, + char **out_iv, + GError **error) +{ + GByteArray *bindata = NULL; + char **lines = NULL; + char **ln = NULL; + const char *pos; + const char *end; + GString *str = NULL; + int enc_tags = 0; + char *iv = NULL; + char *cipher = NULL; + unsigned char *tmp = NULL; + gsize tmp_len = 0; + const char *start_tag; + const char *end_tag; + + switch (key_type) { + case NM_CRYPTO_KEY_TYPE_RSA: + start_tag = pem_rsa_key_begin; + end_tag = pem_rsa_key_end; + break; + case NM_CRYPTO_KEY_TYPE_DSA: + start_tag = pem_dsa_key_begin; + end_tag = pem_dsa_key_end; + break; + default: + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_UNKNOWN_KEY_TYPE, + "Unknown key type %d", + key_type); + g_assert_not_reached (); + return NULL; + } + + pos = find_tag (start_tag, (const char *) contents->data, contents->len); + if (!pos) + goto parse_error; + + pos += strlen (start_tag); + + end = find_tag (end_tag, pos, (const char *) contents->data + contents->len - pos); + if (end == NULL) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("PEM key file had no end tag '%s'."), + end_tag); + goto parse_error; + } + *((char *) end) = '\0'; + + lines = g_strsplit (pos, "\n", 0); + if (!lines || g_strv_length (lines) <= 1) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("Doesn't look like a PEM private key file.")); + goto parse_error; + } + + str = g_string_new_len (NULL, end - pos); + if (!str) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Not enough memory to store PEM file data.")); + goto parse_error; + } + + for (ln = lines; *ln; ln++) { + char *p = *ln; + + /* Chug leading spaces */ + p = g_strstrip (p); + if (!*p) + continue; + + if (!strncmp (p, PROC_TYPE_TAG, strlen (PROC_TYPE_TAG))) { + if (enc_tags++ != 0) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("Malformed PEM file: Proc-Type was not first tag.")); + goto parse_error; + } + + p += strlen (PROC_TYPE_TAG); + if (strcmp (p, "4,ENCRYPTED")) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("Malformed PEM file: unknown Proc-Type tag '%s'."), + p); + goto parse_error; + } + } else if (!strncmp (p, DEK_INFO_TAG, strlen (DEK_INFO_TAG))) { + char *comma; + + if (enc_tags++ != 1) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("Malformed PEM file: DEK-Info was not the second tag.")); + goto parse_error; + } + + p += strlen (DEK_INFO_TAG); + + /* Grab the IV first */ + comma = strchr (p, ','); + if (!comma || (*(comma + 1) == '\0')) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("Malformed PEM file: no IV found in DEK-Info tag.")); + goto parse_error; + } + *comma++ = '\0'; + if (!g_ascii_isxdigit (*comma)) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("Malformed PEM file: invalid format of IV in DEK-Info tag.")); + goto parse_error; + } + iv = g_strdup (comma); + + /* Get the private key cipher */ + if (!strcasecmp (p, "DES-EDE3-CBC")) { + cipher = g_strdup (p); + } else if (!strcasecmp (p, "DES-CBC")) { + cipher = g_strdup (p); + } else { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_UNKNOWN_KEY_TYPE, + _("Malformed PEM file: unknown private key cipher '%s'."), + p); + goto parse_error; + } + } else { + if ((enc_tags != 0) && (enc_tags != 2)) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + "Malformed PEM file: both Proc-Type and DEK-Info tags are required."); + goto parse_error; + } + g_string_append (str, p); + } + } + + tmp = g_base64_decode (str->str, &tmp_len); + if (tmp == NULL || !tmp_len) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_DECODE_FAILED, + _("Could not decode private key.")); + goto parse_error; + } + + if (lines) + g_strfreev (lines); + + bindata = g_byte_array_sized_new (tmp_len); + g_byte_array_append (bindata, tmp, tmp_len); + *out_iv = iv; + *out_cipher = cipher; + return bindata; + +parse_error: + g_free (cipher); + g_free (iv); + if (lines) + g_strfreev (lines); + return NULL; +} + +static GByteArray * +file_to_g_byte_array (const char *filename, + gboolean privkey, + GError **error) +{ + char *contents, *der = NULL; + GByteArray *array = NULL; + gsize length = 0; + const char *pos = NULL; + + if (!g_file_get_contents (filename, &contents, &length, error)) + return NULL; + + if (!privkey) + pos = find_tag (pem_cert_begin, contents, length); + + if (pos) { + const char *end; + + pos += strlen (pem_cert_begin); + end = find_tag (pem_cert_end, pos, contents + length - pos); + if (end == NULL) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("PEM certificate '%s' had no end tag '%s'."), + filename, pem_cert_end); + goto done; + } + + contents[end - contents - 1] = '\0'; + der = (char *) g_base64_decode (pos, &length); + if (der == NULL || !length) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_DECODE_FAILED, + _("Failed to decode certificate.")); + goto done; + } + } + + array = g_byte_array_sized_new (length); + if (!array) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Not enough memory to store certificate data.")); + goto done; + } + + g_byte_array_append (array, der ? (unsigned char *) der : (unsigned char *) contents, length); + if (array->len != length) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Not enough memory to store file data.")); + g_byte_array_free (array, TRUE); + array = NULL; + } + +done: + g_free (der); + g_free (contents); + return array; +} + +/* + * Convert a hex string into bytes. + */ +static char * +convert_iv (const char *src, + gsize *out_len, + GError **error) +{ + int num; + int i; + char conv[3]; + char *c; + + g_return_val_if_fail (src != NULL, NULL); + + num = strlen (src); + if (num % 2) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_RAW_IV_INVALID, + _("IV must be an even number of bytes in length.")); + return NULL; + } + + num /= 2; + c = g_malloc0 (num + 1); + if (c == NULL) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Not enough memory to store the IV.")); + return NULL; + } + + conv[2] = '\0'; + for (i = 0; i < num; i++) { + conv[0] = src[(i * 2)]; + conv[1] = src[(i * 2) + 1]; + if (!g_ascii_isxdigit (conv[0]) || !g_ascii_isxdigit (conv[1])) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_RAW_IV_INVALID, + _("IV contains non-hexadecimal digits.")); + goto error; + } + + c[i] = strtol(conv, NULL, 16); + } + *out_len = num; + return c; + +error: + g_free (c); + return NULL; +} + +static char * +make_des_key (const char *cipher, + const char *salt, + const gsize salt_len, + const char *password, + gsize *out_len, + GError **error) +{ + char *key; + guint32 digest_len; + + g_return_val_if_fail (cipher != NULL, NULL); + g_return_val_if_fail (salt != NULL, NULL); + g_return_val_if_fail (salt_len >= 8, NULL); + g_return_val_if_fail (password != NULL, NULL); + g_return_val_if_fail (out_len != NULL, NULL); + + if (!strcmp (cipher, "DES-EDE3-CBC")) + digest_len = 24; + else if (!strcmp (cipher, "DES-CBC")) + digest_len = 8; + else { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_UNKNOWN_CIPHER, + _("Private key cipher '%s' was unknown."), + cipher); + return NULL; + } + + key = g_malloc0 (digest_len + 1); + if (!key) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Not enough memory to decrypt private key.")); + return NULL; + } + + if (!crypto_md5_hash (salt, + salt_len, + password, + strlen (password), + key, + digest_len, + error)) + goto error; + + *out_len = digest_len; + return key; + +error: + if (key) { + /* Don't leak stale key material */ + memset (key, 0, digest_len); + g_free (key); + } + return NULL; +} + +static char * +decrypt_key (const char *cipher, + int key_type, + GByteArray *data, + const char *iv, + const char *password, + gsize *out_len, + GError **error) +{ + char *bin_iv = NULL; + gsize bin_iv_len = 0; + char *key = NULL; + gsize key_len = 0; + char *output = NULL; + + bin_iv = convert_iv (iv, &bin_iv_len, error); + if (!bin_iv) + return NULL; + + /* Convert the PIN and IV into a DES key */ + key = make_des_key (cipher, bin_iv, bin_iv_len, password, &key_len, error); + if (!key || !key_len) + goto out; + + output = crypto_decrypt (cipher, key_type, + data, + bin_iv, bin_iv_len, + key, key_len, + out_len, + error); + if (!output) + goto out; + + if (*out_len == 0) { + g_free (output); + output = NULL; + goto out; + } + +out: + if (key) { + /* Don't leak stale key material */ + memset (key, 0, key_len); + g_free (key); + } + g_free (bin_iv); + return output; +} + +GByteArray * +crypto_get_private_key_data (GByteArray *contents, + const char *password, + NMCryptoKeyType *out_key_type, + NMCryptoFileFormat *out_file_type, + GError **error) +{ + GByteArray *array = NULL; + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_RSA; + GByteArray *data; + char *iv = NULL; + char *cipher = NULL; + char *decrypted = NULL; + gsize decrypted_len = 0; + + g_return_val_if_fail (contents != NULL, NULL); + g_return_val_if_fail (password != NULL, NULL); + g_return_val_if_fail (out_key_type != NULL, NULL); + g_return_val_if_fail (*out_key_type == NM_CRYPTO_KEY_TYPE_UNKNOWN, NULL); + g_return_val_if_fail (out_file_type != NULL, NULL); + g_return_val_if_fail (*out_file_type == NM_CRYPTO_FILE_FORMAT_UNKNOWN, NULL); + + /* Try PKCS#12 first */ + if (crypto_verify_pkcs12 (contents, password, NULL)) { + *out_key_type = NM_CRYPTO_KEY_TYPE_ENCRYPTED; + *out_file_type = NM_CRYPTO_FILE_FORMAT_PKCS12; + + array = g_byte_array_sized_new (contents->len); + g_byte_array_append (array, contents->data, contents->len); + return array; + } + + /* OpenSSL non-standard legacy PEM files */ + + /* Try RSA keys first */ + data = parse_old_openssl_key_file (contents, key_type, &cipher, &iv, error); + if (!data) { + g_clear_error (error); + + /* DSA next */ + key_type = NM_CRYPTO_KEY_TYPE_DSA; + data = parse_old_openssl_key_file (contents, key_type, &cipher, &iv, error); + if (!data) { + g_clear_error (error); + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("Unable to determine private key type.")); + goto out; + } + } + + decrypted = decrypt_key (cipher, + key_type, + data, + iv, + password, + &decrypted_len, + error); + if (!decrypted) + goto out; + + array = g_byte_array_sized_new (decrypted_len); + if (!array) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Not enough memory to store decrypted private key.")); + goto out; + } + + g_byte_array_append (array, (const guint8 *) decrypted, decrypted_len); + *out_key_type = key_type; + *out_file_type = NM_CRYPTO_FILE_FORMAT_RAW_KEY; + +out: + if (decrypted) { + /* Don't expose key material */ + memset (decrypted, 0, decrypted_len); + g_free (decrypted); + } + if (data) + g_byte_array_free (data, TRUE); + g_free (cipher); + g_free (iv); + return array; +} + +GByteArray * +crypto_get_private_key (const char *file, + const char *password, + NMCryptoKeyType *out_key_type, + NMCryptoFileFormat *out_file_type, + GError **error) +{ + GByteArray *contents; + GByteArray *key = NULL; + + contents = file_to_g_byte_array (file, TRUE, error); + if (contents) { + key = crypto_get_private_key_data (contents, password, out_key_type, out_file_type, error); + g_byte_array_free (contents, TRUE); + } + return key; +} + +GByteArray * +crypto_load_and_verify_certificate (const char *file, + NMCryptoFileFormat *out_file_format, + GError **error) +{ + GByteArray *array; + + g_return_val_if_fail (file != NULL, NULL); + g_return_val_if_fail (out_file_format != NULL, NULL); + g_return_val_if_fail (*out_file_format == NM_CRYPTO_FILE_FORMAT_UNKNOWN, NULL); + + array = file_to_g_byte_array (file, FALSE, error); + if (!array) + return NULL; + + *out_file_format = crypto_verify_cert (array->data, array->len, error); + if (*out_file_format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) { + /* Try PKCS#12 */ + if (crypto_is_pkcs12_data (array)) { + *out_file_format = NM_CRYPTO_FILE_FORMAT_PKCS12; + g_clear_error (error); + } else { + g_byte_array_free (array, TRUE); + array = NULL; + } + } + + return array; +} + +gboolean +crypto_is_pkcs12_data (const GByteArray *data) +{ + GError *error = NULL; + gboolean success; + + g_return_val_if_fail (data != NULL, FALSE); + + success = crypto_verify_pkcs12 (data, NULL, &error); + if (success) + return TRUE; + + /* If the error was just a decryption error, then it's pkcs#12 */ + if (error) { + if (g_error_matches (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED)) + success = TRUE; + g_error_free (error); + } + + return success; +} + +gboolean +crypto_is_pkcs12_file (const char *file, GError **error) +{ + GByteArray *contents; + gboolean success = FALSE; + + g_return_val_if_fail (file != NULL, FALSE); + + contents = file_to_g_byte_array (file, TRUE, error); + if (contents) { + success = crypto_is_pkcs12_data (contents); + g_byte_array_free (contents, TRUE); + } + return success; +} + diff --git a/libnm-util/crypto.h b/libnm-util/crypto.h new file mode 100644 index 00000000..38471cea --- /dev/null +++ b/libnm-util/crypto.h @@ -0,0 +1,131 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + */ + +#include <glib.h> + +#define MD5_HASH_LEN 20 +#define CIPHER_DES_EDE3_CBC "DES-EDE3-CBC" +#define CIPHER_DES_CBC "DES-CBC" + +enum { + NM_CRYPTO_ERR_NONE = 0, + NM_CRYPTO_ERR_INIT_FAILED, + NM_CRYPTO_ERR_CANT_READ_FILE, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + NM_CRYPTO_ERR_CERT_FORMAT_INVALID, + NM_CRYPTO_ERR_DECODE_FAILED, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + NM_CRYPTO_ERR_UNKNOWN_KEY_TYPE, + NM_CRYPTO_ERR_UNKNOWN_CIPHER, + NM_CRYPTO_ERR_RAW_IV_INVALID, + NM_CRYPTO_ERR_MD5_INIT_FAILED, + NM_CRYPTO_ERR_CIPHER_INIT_FAILED, + NM_CRYPTO_ERR_CIPHER_SET_KEY_FAILED, + NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + NM_CRYPTO_ERR_INVALID_PASSWORD, + NM_CRYPTO_ERR_CIPHER_ENCRYPT_FAILED, + NM_CRYPTO_ERR_RANDOMIZE_FAILED +}; + +typedef enum { + NM_CRYPTO_KEY_TYPE_UNKNOWN = 0, + NM_CRYPTO_KEY_TYPE_RSA, + NM_CRYPTO_KEY_TYPE_DSA, + NM_CRYPTO_KEY_TYPE_ENCRYPTED +} NMCryptoKeyType; + +typedef enum { + NM_CRYPTO_FILE_FORMAT_UNKNOWN = 0, + NM_CRYPTO_FILE_FORMAT_X509, + NM_CRYPTO_FILE_FORMAT_RAW_KEY, + NM_CRYPTO_FILE_FORMAT_PKCS12 +} NMCryptoFileFormat; + +#define NM_CRYPTO_ERROR _nm_crypto_error_quark () +GQuark _nm_crypto_error_quark (void); + +gboolean crypto_init (GError **error); + +void crypto_deinit (void); + +GByteArray * crypto_get_private_key_data (GByteArray *contents, + const char *password, + NMCryptoKeyType *out_key_type, + NMCryptoFileFormat *out_file_format, + GError **error); + +GByteArray * crypto_get_private_key (const char *file, + const char *password, + NMCryptoKeyType *out_key_type, + NMCryptoFileFormat *out_file_format, + GError **error); + +GByteArray * crypto_load_and_verify_certificate (const char *file, + NMCryptoFileFormat *out_file_format, + GError **error); + +gboolean crypto_is_pkcs12_file (const char *file, GError **error); + +gboolean crypto_is_pkcs12_data (const GByteArray *data); + + +/* Internal utils API bits for crypto providers */ + +gboolean crypto_md5_hash (const char *salt, + const gsize salt_len, + const char *password, + gsize password_len, + char *buffer, + gsize buflen, + GError **error); + +char * crypto_decrypt (const char *cipher, + int key_type, + GByteArray *data, + const char *iv, + const gsize iv_len, + const char *key, + const gsize key_len, + gsize *out_len, + GError **error); + +char * crypto_encrypt (const char *cipher, + const GByteArray *data, + const char *iv, + gsize iv_len, + const char *key, + gsize key_len, + gsize *out_len, + GError **error); + +gboolean crypto_randomize (void *buffer, gsize buffer_len, GError **error); + +NMCryptoFileFormat crypto_verify_cert (const unsigned char *data, + gsize len, + GError **error); + +gboolean crypto_verify_pkcs12 (const GByteArray *data, + const char *password, + GError **error); + diff --git a/libnm-util/crypto_gnutls.c b/libnm-util/crypto_gnutls.c new file mode 100644 index 00000000..edfc16af --- /dev/null +++ b/libnm-util/crypto_gnutls.c @@ -0,0 +1,448 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager Wireless Applet -- Display wireless access points and allow user control + * + * Dan Williams <dcbw@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2009 Red Hat, Inc. + */ + +#include <glib.h> +#include <glib/gi18n.h> + +#include <gcrypt.h> +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> +#include <gnutls/pkcs12.h> + +#include "crypto.h" + +#define SALT_LEN 8 + +static gboolean initialized = FALSE; + +gboolean +crypto_init (GError **error) +{ + if (initialized) + return TRUE; + + if (gnutls_global_init() != 0) { + gnutls_global_deinit(); + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_INIT_FAILED, + "%s", + _("Failed to initialize the crypto engine.")); + return FALSE; + } + + initialized = TRUE; + return TRUE; +} + +void +crypto_deinit (void) +{ + if (initialized) + gnutls_global_deinit(); +} + +gboolean +crypto_md5_hash (const char *salt, + const gsize salt_len, + const char *password, + gsize password_len, + char *buffer, + gsize buflen, + GError **error) +{ + gcry_md_hd_t ctx; + gcry_error_t err; + int nkey = buflen; + const gsize digest_len = 16; + int count = 0; + char digest[MD5_HASH_LEN]; + char *p = buffer; + + if (salt) + g_return_val_if_fail (salt_len >= SALT_LEN, FALSE); + + g_return_val_if_fail (password != NULL, FALSE); + g_return_val_if_fail (password_len > 0, FALSE); + g_return_val_if_fail (buffer != NULL, FALSE); + g_return_val_if_fail (buflen > 0, FALSE); + + err = gcry_md_open (&ctx, GCRY_MD_MD5, 0); + if (err) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_MD5_INIT_FAILED, + _("Failed to initialize the MD5 engine: %s / %s."), + gcry_strsource (err), gcry_strerror (err)); + return FALSE; + } + + while (nkey > 0) { + int i = 0; + + if (count++) + gcry_md_write (ctx, digest, digest_len); + gcry_md_write (ctx, password, password_len); + if (salt) + gcry_md_write (ctx, salt, SALT_LEN); /* Only use 8 bytes of salt */ + gcry_md_final (ctx); + memcpy (digest, gcry_md_read (ctx, 0), digest_len); + gcry_md_reset (ctx); + + while (nkey && (i < digest_len)) { + *(p++) = digest[i++]; + nkey--; + } + } + + memset (digest, 0, sizeof (digest)); + gcry_md_close (ctx); + return TRUE; +} + +char * +crypto_decrypt (const char *cipher, + int key_type, + GByteArray *data, + const char *iv, + const gsize iv_len, + const char *key, + const gsize key_len, + gsize *out_len, + GError **error) +{ + gcry_cipher_hd_t ctx; + gcry_error_t err; + int cipher_mech, i; + char *output = NULL; + gboolean success = FALSE; + gsize pad_len, real_iv_len; + + if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) { + cipher_mech = GCRY_CIPHER_3DES; + real_iv_len = SALT_LEN; + } else if (!strcmp (cipher, CIPHER_DES_CBC)) { + cipher_mech = GCRY_CIPHER_DES; + real_iv_len = SALT_LEN; + } else { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_UNKNOWN_CIPHER, + _("Private key cipher '%s' was unknown."), + cipher); + return NULL; + } + + if (iv_len < real_iv_len) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_RAW_IV_INVALID, + _("Invalid IV length (must be at least %zd)."), + real_iv_len); + return NULL; + } + + output = g_malloc0 (data->len); + if (!output) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Not enough memory for decrypted key buffer.")); + return NULL; + } + + err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0); + if (err) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_INIT_FAILED, + _("Failed to initialize the decryption cipher context: %s / %s."), + gcry_strsource (err), gcry_strerror (err)); + goto out; + } + + err = gcry_cipher_setkey (ctx, key, key_len); + if (err) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_SET_KEY_FAILED, + _("Failed to set symmetric key for decryption: %s / %s."), + gcry_strsource (err), gcry_strerror (err)); + goto out; + } + + err = gcry_cipher_setiv (ctx, iv, iv_len); + if (err) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED, + _("Failed to set IV for decryption: %s / %s."), + gcry_strsource (err), gcry_strerror (err)); + goto out; + } + + err = gcry_cipher_decrypt (ctx, output, data->len, data->data, data->len); + if (err) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Failed to decrypt the private key: %s / %s."), + gcry_strsource (err), gcry_strerror (err)); + goto out; + } + pad_len = output[data->len - 1]; + + /* Check if the padding at the end of the decrypted data is valid */ + if (pad_len == 0 || pad_len > real_iv_len) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Failed to decrypt the private key: unexpected padding length.")); + goto out; + } + + /* Validate tail padding; last byte is the padding size, and all pad bytes + * should contain the padding size. + */ + for (i = 1; i <= pad_len; ++i) { + if (output[data->len - i] != pad_len) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Failed to decrypt the private key.")); + goto out; + } + } + + *out_len = data->len - pad_len; + success = TRUE; + +out: + if (!success) { + if (output) { + /* Don't expose key material */ + memset (output, 0, data->len); + g_free (output); + output = NULL; + } + } + gcry_cipher_close (ctx); + return output; +} + +char * +crypto_encrypt (const char *cipher, + const GByteArray *data, + const char *iv, + const gsize iv_len, + const char *key, + gsize key_len, + gsize *out_len, + GError **error) +{ + gcry_cipher_hd_t ctx; + gcry_error_t err; + int cipher_mech; + char *output = NULL; + gboolean success = FALSE; + gsize padded_buf_len, pad_len, output_len; + char *padded_buf = NULL; + guint32 i; + + if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) + cipher_mech = GCRY_CIPHER_3DES; + else { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_UNKNOWN_CIPHER, + _("Private key cipher '%s' was unknown."), + cipher); + return NULL; + } + + /* If data->len % ivlen == 0, then we add another complete block + * onto the end so that the decrypter knows there's padding. + */ + pad_len = iv_len - (data->len % iv_len); + output_len = padded_buf_len = data->len + pad_len; + padded_buf = g_malloc0 (padded_buf_len); + + memcpy (padded_buf, data->data, data->len); + for (i = 0; i < pad_len; i++) + padded_buf[data->len + i] = (guint8) (pad_len & 0xFF); + + output = g_malloc0 (output_len); + if (!output) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Could not allocate memory for encrypting.")); + return NULL; + } + + err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0); + if (err) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_INIT_FAILED, + _("Failed to initialize the encryption cipher context: %s / %s."), + gcry_strsource (err), gcry_strerror (err)); + goto out; + } + + err = gcry_cipher_setkey (ctx, key, key_len); + if (err) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_SET_KEY_FAILED, + _("Failed to set symmetric key for encryption: %s / %s."), + gcry_strsource (err), gcry_strerror (err)); + goto out; + } + + /* gcrypt only wants 8 bytes of the IV (same as the DES block length) */ + err = gcry_cipher_setiv (ctx, iv, SALT_LEN); + if (err) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED, + _("Failed to set IV for encryption: %s / %s."), + gcry_strsource (err), gcry_strerror (err)); + goto out; + } + + err = gcry_cipher_encrypt (ctx, output, output_len, padded_buf, padded_buf_len); + if (err) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Failed to encrypt the data: %s / %s."), + gcry_strsource (err), gcry_strerror (err)); + goto out; + } + + *out_len = output_len; + success = TRUE; + +out: + if (padded_buf) { + memset (padded_buf, 0, padded_buf_len); + g_free (padded_buf); + padded_buf = NULL; + } + + if (!success) { + if (output) { + /* Don't expose key material */ + memset (output, 0, output_len); + g_free (output); + output = NULL; + } + } + gcry_cipher_close (ctx); + return output; +} + +NMCryptoFileFormat +crypto_verify_cert (const unsigned char *data, + gsize len, + GError **error) +{ + gnutls_x509_crt_t der; + gnutls_datum dt; + int err; + + err = gnutls_x509_crt_init (&der); + if (err < 0) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CERT_FORMAT_INVALID, + _("Error initializing certificate data: %s"), + gnutls_strerror (err)); + return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + } + + /* Try DER first */ + dt.data = (unsigned char *) data; + dt.size = len; + err = gnutls_x509_crt_import (der, &dt, GNUTLS_X509_FMT_DER); + if (err == GNUTLS_E_SUCCESS) { + gnutls_x509_crt_deinit (der); + return NM_CRYPTO_FILE_FORMAT_X509; + } + + /* And PEM next */ + err = gnutls_x509_crt_import (der, &dt, GNUTLS_X509_FMT_PEM); + gnutls_x509_crt_deinit (der); + if (err == GNUTLS_E_SUCCESS) + return NM_CRYPTO_FILE_FORMAT_X509; + + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CERT_FORMAT_INVALID, + _("Couldn't decode certificate: %s"), + gnutls_strerror (err)); + return NM_CRYPTO_FILE_FORMAT_UNKNOWN; +} + +gboolean +crypto_verify_pkcs12 (const GByteArray *data, + const char *password, + GError **error) +{ + gnutls_pkcs12_t p12; + gnutls_datum dt; + gboolean success = FALSE; + int err; + + g_return_val_if_fail (data != NULL, FALSE); + + dt.data = (unsigned char *) data->data; + dt.size = data->len; + + err = gnutls_pkcs12_init (&p12); + if (err < 0) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_DECODE_FAILED, + _("Couldn't initialize PKCS#12 decoder: %s"), + gnutls_strerror (err)); + return FALSE; + } + + /* DER first */ + err = gnutls_pkcs12_import (p12, &dt, GNUTLS_X509_FMT_DER, 0); + if (err < 0) { + /* PEM next */ + err = gnutls_pkcs12_import (p12, &dt, GNUTLS_X509_FMT_PEM, 0); + if (err < 0) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("Couldn't decode PKCS#12 file: %s"), + gnutls_strerror (err)); + goto out; + } + } + + err = gnutls_pkcs12_verify_mac (p12, password); + if (err == GNUTLS_E_SUCCESS) + success = TRUE; + else { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Couldn't verify PKCS#12 file: %s"), + gnutls_strerror (err)); + } + +out: + gnutls_pkcs12_deinit (p12); + return success; +} + +gboolean +crypto_randomize (void *buffer, gsize buffer_len, GError **error) +{ + gcry_randomize (buffer, buffer_len, GCRY_STRONG_RANDOM); + return TRUE; +} + diff --git a/libnm-util/crypto_nss.c b/libnm-util/crypto_nss.c new file mode 100644 index 00000000..490d5fe9 --- /dev/null +++ b/libnm-util/crypto_nss.c @@ -0,0 +1,562 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2009 Red Hat, Inc. + */ + +#include "config.h" + +#include <glib.h> +#include <glib/gi18n.h> + +#include <prinit.h> +#include <nss.h> +#include <pk11pub.h> +#include <pkcs11t.h> +#include <cert.h> +#include <prerror.h> +#include <p12.h> +#include <ciferfam.h> +#include <p12plcy.h> + +#include "crypto.h" + +static gboolean initialized = FALSE; + +gboolean +crypto_init (GError **error) +{ + SECStatus ret; + + if (initialized) + return TRUE; + + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1); + ret = NSS_NoDB_Init (NULL); + if (ret != SECSuccess) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_INIT_FAILED, + _("Failed to initialize the crypto engine: %d."), + PR_GetError ()); + PR_Cleanup (); + return FALSE; + } + + SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1); + SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1); + SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1); + SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1); + SEC_PKCS12EnableCipher(PKCS12_DES_56, 1); + SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1); + SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1); + + initialized = TRUE; + return TRUE; +} + +void +crypto_deinit (void) +{ + if (initialized) { + NSS_Shutdown (); + PR_Cleanup (); + } +} + +gboolean +crypto_md5_hash (const char *salt, + const gsize salt_len, + const char *password, + gsize password_len, + char *buffer, + gsize buflen, + GError **error) +{ + PK11Context *ctx; + int nkey = buflen; + unsigned int digest_len; + int count = 0; + char digest[MD5_HASH_LEN]; + char *p = buffer; + + if (salt) + g_return_val_if_fail (salt_len >= 8, FALSE); + + g_return_val_if_fail (password != NULL, FALSE); + g_return_val_if_fail (password_len > 0, FALSE); + g_return_val_if_fail (buffer != NULL, FALSE); + g_return_val_if_fail (buflen > 0, FALSE); + + ctx = PK11_CreateDigestContext (SEC_OID_MD5); + if (!ctx) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_MD5_INIT_FAILED, + _("Failed to initialize the MD5 context: %d."), + PORT_GetError ()); + return FALSE; + } + + while (nkey > 0) { + int i = 0; + + PK11_DigestBegin (ctx); + if (count++) + PK11_DigestOp (ctx, (const unsigned char *) digest, digest_len); + PK11_DigestOp (ctx, (const unsigned char *) password, password_len); + if (salt) + PK11_DigestOp (ctx, (const unsigned char *) salt, 8); /* Only use 8 bytes of salt */ + PK11_DigestFinal (ctx, (unsigned char *) digest, &digest_len, sizeof (digest)); + + while (nkey && (i < digest_len)) { + *(p++) = digest[i++]; + nkey--; + } + } + + memset (digest, 0, sizeof (digest)); + PK11_DestroyContext (ctx, PR_TRUE); + return TRUE; +} + +char * +crypto_decrypt (const char *cipher, + int key_type, + GByteArray *data, + const char *iv, + const gsize iv_len, + const char *key, + const gsize key_len, + gsize *out_len, + GError **error) +{ + char *output = NULL; + int decrypted_len = 0; + CK_MECHANISM_TYPE cipher_mech; + PK11SlotInfo *slot = NULL; + SECItem key_item; + PK11SymKey *sym_key = NULL; + SECItem *sec_param = NULL; + PK11Context *ctx = NULL; + SECStatus s; + gboolean success = FALSE; + unsigned int pad_len = 0, extra = 0; + guint32 i, real_iv_len = 0; + + if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) { + cipher_mech = CKM_DES3_CBC_PAD; + real_iv_len = 8; + } else if (!strcmp (cipher, CIPHER_DES_CBC)) { + cipher_mech = CKM_DES_CBC_PAD; + real_iv_len = 8; + } else { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_UNKNOWN_CIPHER, + _("Private key cipher '%s' was unknown."), + cipher); + return NULL; + } + + if (iv_len < real_iv_len) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_RAW_IV_INVALID, + _("Invalid IV length (must be at least %d)."), + real_iv_len); + return NULL; + } + + output = g_malloc0 (data->len); + if (!output) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Not enough memory for decrypted key buffer.")); + return NULL; + } + + slot = PK11_GetBestSlot (cipher_mech, NULL); + if (!slot) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_INIT_FAILED, + _("Failed to initialize the decryption cipher slot.")); + goto out; + } + + key_item.data = (unsigned char *) key; + key_item.len = key_len; + sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL); + if (!sym_key) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_SET_KEY_FAILED, + _("Failed to set symmetric key for decryption.")); + goto out; + } + + key_item.data = (unsigned char *) iv; + key_item.len = real_iv_len; + sec_param = PK11_ParamFromIV (cipher_mech, &key_item); + if (!sec_param) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED, + _("Failed to set IV for decryption.")); + goto out; + } + + ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_DECRYPT, sym_key, sec_param); + if (!ctx) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_INIT_FAILED, + _("Failed to initialize the decryption context.")); + goto out; + } + + s = PK11_CipherOp (ctx, + (unsigned char *) output, + &decrypted_len, + data->len, + data->data, + data->len); + if (s != SECSuccess) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Failed to decrypt the private key: %d."), + PORT_GetError ()); + goto out; + } + + if (decrypted_len > data->len) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Failed to decrypt the private key: decrypted data too large.")); + goto out; + } + + s = PK11_DigestFinal (ctx, + (unsigned char *) (output + decrypted_len), + &extra, + data->len - decrypted_len); + if (s != SECSuccess) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Failed to finalize decryption of the private key: %d."), + PORT_GetError ()); + goto out; + } + decrypted_len += extra; + pad_len = data->len - decrypted_len; + + /* Check if the padding at the end of the decrypted data is valid */ + if (pad_len == 0 || pad_len > real_iv_len) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Failed to decrypt the private key: unexpected padding length.")); + goto out; + } + + /* Validate tail padding; last byte is the padding size, and all pad bytes + * should contain the padding size. + */ + for (i = pad_len; i > 0; i--) { + if (output[data->len - i] != pad_len) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Failed to decrypt the private key.")); + goto out; + } + } + + *out_len = decrypted_len; + success = TRUE; + +out: + if (ctx) + PK11_DestroyContext (ctx, PR_TRUE); + if (sym_key) + PK11_FreeSymKey (sym_key); + if (sec_param) + SECITEM_FreeItem (sec_param, PR_TRUE); + if (slot) + PK11_FreeSlot (slot); + + if (!success) { + if (output) { + /* Don't expose key material */ + memset (output, 0, data->len); + g_free (output); + output = NULL; + } + } + return output; +} + +char * +crypto_encrypt (const char *cipher, + const GByteArray *data, + const char *iv, + gsize iv_len, + const char *key, + gsize key_len, + gsize *out_len, + GError **error) +{ + SECStatus ret; + CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD; + PK11SlotInfo *slot = NULL; + SECItem key_item = { .data = (unsigned char *) key, .len = key_len }; + SECItem iv_item = { .data = (unsigned char *) iv, .len = iv_len }; + PK11SymKey *sym_key = NULL; + SECItem *sec_param = NULL; + PK11Context *ctx = NULL; + unsigned char *output, *padded_buf; + gsize output_len; + int encrypted_len = 0, i; + gboolean success = FALSE; + gsize padded_buf_len, pad_len; + + if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) + cipher_mech = CKM_DES3_CBC_PAD; + else { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_UNKNOWN_CIPHER, + _("Private key cipher '%s' was unknown."), + cipher); + return NULL; + } + + /* If data->len % ivlen == 0, then we add another complete block + * onto the end so that the decrypter knows there's padding. + */ + pad_len = iv_len - (data->len % iv_len); + output_len = padded_buf_len = data->len + pad_len; + padded_buf = g_malloc0 (padded_buf_len); + + memcpy (padded_buf, data->data, data->len); + for (i = 0; i < pad_len; i++) + padded_buf[data->len + i] = (guint8) (pad_len & 0xFF); + + output = g_malloc0 (output_len); + if (!output) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Could not allocate memory for encrypting.")); + return NULL; + } + + slot = PK11_GetBestSlot (cipher_mech, NULL); + if (!slot) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_INIT_FAILED, + _("Failed to initialize the encryption cipher slot.")); + goto out; + } + + sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); + if (!sym_key) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_SET_KEY_FAILED, + _("Failed to set symmetric key for encryption.")); + goto out; + } + + sec_param = PK11_ParamFromIV (cipher_mech, &iv_item); + if (!sec_param) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED, + _("Failed to set IV for encryption.")); + goto out; + } + + ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_ENCRYPT, sym_key, sec_param); + if (!ctx) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_INIT_FAILED, + _("Failed to initialize the encryption context.")); + goto out; + } + + ret = PK11_CipherOp (ctx, output, &encrypted_len, output_len, padded_buf, padded_buf_len); + if (ret != SECSuccess) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_ENCRYPT_FAILED, + _("Failed to encrypt: %d."), + PORT_GetError ()); + goto out; + } + + if (encrypted_len != output_len) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_ENCRYPT_FAILED, + _("Unexpected amount of data after encrypting.")); + goto out; + } + + *out_len = encrypted_len; + success = TRUE; + +out: + if (ctx) + PK11_DestroyContext (ctx, PR_TRUE); + if (sym_key) + PK11_FreeSymKey (sym_key); + if (sec_param) + SECITEM_FreeItem (sec_param, PR_TRUE); + if (slot) + PK11_FreeSlot (slot); + + if (padded_buf) { + memset (padded_buf, 0, padded_buf_len); + g_free (padded_buf); + padded_buf = NULL; + } + + if (!success) { + memset (output, 0, output_len); + g_free (output); + output = NULL; + } + return (char *) output; +} + +NMCryptoFileFormat +crypto_verify_cert (const unsigned char *data, + gsize len, + GError **error) +{ + CERTCertificate *cert; + + /* Try DER/PEM first */ + cert = CERT_DecodeCertFromPackage ((char *) data, len); + if (!cert) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CERT_FORMAT_INVALID, + _("Couldn't decode certificate: %d"), + PORT_GetError()); + return NM_CRYPTO_FILE_FORMAT_UNKNOWN; + } + + CERT_DestroyCertificate (cert); + return NM_CRYPTO_FILE_FORMAT_X509; +} + +gboolean +crypto_verify_pkcs12 (const GByteArray *data, + const char *password, + GError **error) +{ + SEC_PKCS12DecoderContext *p12ctx = NULL; + SECItem pw = { 0 }; + PK11SlotInfo *slot = NULL; + SECStatus s; + char *ucs2_password; + glong ucs2_chars = 0; +#ifndef WORDS_BIGENDIAN + guint16 *p; +#endif /* WORDS_BIGENDIAN */ + + if (error) + g_return_val_if_fail (*error == NULL, FALSE); + + /* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do + * any conversions for us. + */ + if (password && strlen (password)) { + ucs2_password = (char *) g_utf8_to_utf16 (password, strlen (password), NULL, &ucs2_chars, NULL); + if (!ucs2_password || !ucs2_chars) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_INVALID_PASSWORD, + _("Couldn't convert password to UCS2: %d"), + PORT_GetError()); + return FALSE; + } + + ucs2_chars *= 2; /* convert # UCS2 characters -> bytes */ + pw.data = PORT_ZAlloc(ucs2_chars + 2); + memcpy (pw.data, ucs2_password, ucs2_chars); + pw.len = ucs2_chars + 2; /* include terminating NULL */ + + memset (ucs2_password, 0, ucs2_chars); + g_free (ucs2_password); + +#ifndef WORDS_BIGENDIAN + for (p = (guint16 *) pw.data; p < (guint16 *) (pw.data + pw.len); p++) + *p = GUINT16_SWAP_LE_BE (*p); +#endif /* WORDS_BIGENDIAN */ + } else { + /* NULL password */ + pw.data = NULL; + pw.len = 0; + } + + slot = PK11_GetInternalKeySlot(); + p12ctx = SEC_PKCS12DecoderStart (&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL); + if (!p12ctx) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_DECODE_FAILED, + _("Couldn't initialize PKCS#12 decoder: %d"), + PORT_GetError()); + goto error; + } + + s = SEC_PKCS12DecoderUpdate (p12ctx, data->data, data->len); + if (s != SECSuccess) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_FILE_FORMAT_INVALID, + _("Couldn't decode PKCS#12 file: %d"), + PORT_GetError()); + goto error; + } + + s = SEC_PKCS12DecoderVerify (p12ctx); + if (s != SECSuccess) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED, + _("Couldn't verify PKCS#12 file: %d"), + PORT_GetError()); + goto error; + } + + SEC_PKCS12DecoderFinish (p12ctx); + SECITEM_ZfreeItem (&pw, PR_FALSE); + return TRUE; + +error: + if (p12ctx) + SEC_PKCS12DecoderFinish (p12ctx); + + if (slot) + PK11_FreeSlot(slot); + + SECITEM_ZfreeItem (&pw, PR_FALSE); + return FALSE; +} + +gboolean +crypto_randomize (void *buffer, gsize buffer_len, GError **error) +{ + SECStatus s; + + s = PK11_GenerateRandom (buffer, buffer_len); + if (s != SECSuccess) { + g_set_error_literal (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_RANDOMIZE_FAILED, + _("Could not generate random data.")); + return FALSE; + } + return TRUE; +} + diff --git a/libnm-util/libnm-util.pc.in b/libnm-util/libnm-util.pc.in new file mode 100644 index 00000000..a6e8ee59 --- /dev/null +++ b/libnm-util/libnm-util.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnm-util +Description: Convenience library for clients of NetworkManager +Version: @VERSION@ +Requires: glib-2.0 dbus-glib-1 +Cflags: -I${includedir}/NetworkManager +Libs: -L${libdir} -lnm-util + + diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver new file mode 100644 index 00000000..ed1d8a48 --- /dev/null +++ b/libnm-util/libnm-util.ver @@ -0,0 +1,394 @@ +{ +global: + nm_connection_add_setting; + nm_connection_clear_secrets; + nm_connection_compare; + nm_connection_create_setting; + nm_connection_dump; + nm_connection_duplicate; + nm_connection_error_get_type; + nm_connection_error_quark; + nm_connection_for_each_setting_value; + nm_connection_get_path; + nm_connection_get_scope; + nm_connection_get_setting; + nm_connection_get_setting_by_name; + nm_connection_get_type; + nm_connection_lookup_setting_type; + nm_connection_lookup_setting_type_by_quark; + nm_connection_need_secrets; + nm_connection_new; + nm_connection_new_from_hash; + nm_connection_remove_setting; + nm_connection_replace_settings; + nm_connection_set_path; + nm_connection_set_scope; + nm_connection_to_hash; + nm_connection_update_secrets; + nm_connection_verify; + nm_setting_802_1x_add_eap_method; + nm_setting_802_1x_clear_eap_methods; + nm_setting_802_1x_error_get_type; + nm_setting_802_1x_error_quark; + nm_setting_802_1x_get_anonymous_identity; + nm_setting_802_1x_get_ca_cert; + nm_setting_802_1x_get_ca_cert_blob; + nm_setting_802_1x_set_ca_cert_from_file; + nm_setting_802_1x_get_ca_cert_path; + nm_setting_802_1x_get_ca_cert_scheme; + nm_setting_802_1x_set_ca_cert; + nm_setting_802_1x_get_ca_path; + nm_setting_802_1x_get_client_cert; + nm_setting_802_1x_get_client_cert_blob; + nm_setting_802_1x_set_client_cert_from_file; + nm_setting_802_1x_get_client_cert_path; + nm_setting_802_1x_get_client_cert_scheme; + nm_setting_802_1x_set_client_cert; + nm_setting_802_1x_get_eap_method; + nm_setting_802_1x_get_identity; + nm_setting_802_1x_get_num_eap_methods; + nm_setting_802_1x_get_password; + nm_setting_802_1x_get_phase1_fast_provisioning; + nm_setting_802_1x_get_phase1_peaplabel; + nm_setting_802_1x_get_phase1_peapver; + nm_setting_802_1x_get_phase2_auth; + nm_setting_802_1x_get_phase2_autheap; + nm_setting_802_1x_get_phase2_ca_cert; + nm_setting_802_1x_get_phase2_ca_cert_blob; + nm_setting_802_1x_set_phase2_ca_cert_from_file; + nm_setting_802_1x_get_phase2_ca_cert_path; + nm_setting_802_1x_get_phase2_ca_cert_scheme; + nm_setting_802_1x_set_phase2_ca_cert; + nm_setting_802_1x_get_phase2_ca_path; + nm_setting_802_1x_get_phase2_client_cert; + nm_setting_802_1x_get_phase2_client_cert_blob; + nm_setting_802_1x_set_phase2_client_cert_from_file; + nm_setting_802_1x_get_phase2_client_cert_path; + nm_setting_802_1x_get_phase2_client_cert_scheme; + nm_setting_802_1x_set_phase2_client_cert; + nm_setting_802_1x_get_phase2_private_key; + nm_setting_802_1x_get_phase2_private_key_blob; + nm_setting_802_1x_get_phase2_private_key_format; + nm_setting_802_1x_set_phase2_private_key_from_file; + nm_setting_802_1x_get_phase2_private_key_password; + nm_setting_802_1x_get_phase2_private_key_path; + nm_setting_802_1x_get_phase2_private_key_scheme; + nm_setting_802_1x_get_phase2_private_key_type; + nm_setting_802_1x_set_phase2_private_key; + nm_setting_802_1x_get_pin; + nm_setting_802_1x_get_private_key; + nm_setting_802_1x_get_private_key_blob; + nm_setting_802_1x_get_private_key_format; + nm_setting_802_1x_set_private_key_from_file; + nm_setting_802_1x_get_private_key_password; + nm_setting_802_1x_get_private_key_path; + nm_setting_802_1x_get_private_key_scheme; + nm_setting_802_1x_get_private_key_type; + nm_setting_802_1x_set_private_key; + nm_setting_802_1x_get_psk; + nm_setting_802_1x_get_system_ca_certs; + nm_setting_802_1x_get_type; + nm_setting_802_1x_new; + nm_setting_802_1x_remove_eap_method; + nm_setting_bluetooth_error_get_type; + nm_setting_bluetooth_error_quark; + nm_setting_bluetooth_get_type; + nm_setting_bluetooth_new; + nm_setting_bluetooth_get_bdaddr; + nm_setting_bluetooth_get_connection_type; + nm_setting_cdma_error_get_type; + nm_setting_cdma_error_quark; + nm_setting_cdma_get_type; + nm_setting_cdma_new; + nm_setting_cdma_get_number; + nm_setting_cdma_get_username; + nm_setting_cdma_get_password; + nm_setting_clear_secrets; + nm_setting_compare; + nm_setting_connection_error_get_type; + nm_setting_connection_error_quark; + nm_setting_connection_get_type; + nm_setting_connection_new; + nm_setting_connection_get_id; + nm_setting_connection_get_uuid; + nm_setting_connection_get_connection_type; + nm_setting_connection_get_autoconnect; + nm_setting_connection_get_timestamp; + nm_setting_connection_get_read_only; + nm_setting_duplicate; + nm_setting_enumerate_values; + nm_setting_error_get_type; + nm_setting_error_quark; + nm_setting_new_from_hash; + nm_setting_get_name; + nm_setting_get_type; + nm_setting_gsm_error_get_type; + nm_setting_gsm_error_quark; + nm_setting_gsm_get_type; + nm_setting_gsm_new; + nm_setting_gsm_get_number; + nm_setting_gsm_get_username; + nm_setting_gsm_get_password; + nm_setting_gsm_get_apn; + nm_setting_gsm_get_network_id; + nm_setting_gsm_get_network_type; + nm_setting_gsm_get_allowed_bands; + nm_setting_gsm_get_band; + nm_setting_gsm_get_pin; + nm_setting_gsm_get_puk; + nm_setting_gsm_get_home_only; + nm_setting_ip4_config_error_get_type; + nm_setting_ip4_config_error_quark; + nm_setting_ip4_config_get_type; + nm_setting_ip4_config_new; + nm_setting_ip4_config_get_method; + nm_setting_ip4_config_get_num_dns; + nm_setting_ip4_config_get_dns; + nm_setting_ip4_config_add_dns; + nm_setting_ip4_config_remove_dns; + nm_setting_ip4_config_clear_dns; + nm_setting_ip4_config_get_num_dns_searches; + nm_setting_ip4_config_get_dns_search; + nm_setting_ip4_config_add_dns_search; + nm_setting_ip4_config_remove_dns_search; + nm_setting_ip4_config_clear_dns_searches; + nm_setting_ip4_config_get_num_addresses; + nm_setting_ip4_config_get_address; + nm_setting_ip4_config_add_address; + nm_setting_ip4_config_remove_address; + nm_setting_ip4_config_clear_addresses; + nm_setting_ip4_config_get_num_routes; + nm_setting_ip4_config_get_route; + nm_setting_ip4_config_add_route; + nm_setting_ip4_config_remove_route; + nm_setting_ip4_config_clear_routes; + nm_setting_ip4_config_get_ignore_auto_routes; + nm_setting_ip4_config_get_ignore_auto_dns; + nm_setting_ip4_config_get_dhcp_client_id; + nm_setting_ip4_config_get_dhcp_hostname; + nm_setting_ip4_config_get_dhcp_send_hostname; + nm_setting_ip4_config_get_never_default; + nm_setting_ip4_config_get_may_fail; + nm_ip6_address_new; + nm_ip6_address_dup; + nm_ip6_address_ref; + nm_ip6_address_unref; + nm_ip6_address_compare; + nm_ip6_address_get_address; + nm_ip6_address_set_address; + nm_ip6_address_get_gateway; + nm_ip6_address_set_gateway; + nm_ip6_address_get_prefix; + nm_ip6_address_set_prefix; + nm_ip6_route_new; + nm_ip6_route_dup; + nm_ip6_route_ref; + nm_ip6_route_unref; + nm_ip6_route_compare; + nm_ip6_route_get_dest; + nm_ip6_route_set_dest; + nm_ip6_route_get_prefix; + nm_ip6_route_set_prefix; + nm_ip6_route_get_next_hop; + nm_ip6_route_set_next_hop; + nm_ip6_route_get_metric; + nm_ip6_route_set_metric; + nm_setting_ip6_config_error_get_type; + nm_setting_ip6_config_error_quark; + nm_setting_ip6_config_get_type; + nm_setting_ip6_config_new; + nm_setting_ip6_config_get_method; + nm_setting_ip6_config_get_num_dns; + nm_setting_ip6_config_get_dns; + nm_setting_ip6_config_add_dns; + nm_setting_ip6_config_remove_dns; + nm_setting_ip6_config_clear_dns; + nm_setting_ip6_config_get_num_dns_searches; + nm_setting_ip6_config_get_dns_search; + nm_setting_ip6_config_add_dns_search; + nm_setting_ip6_config_remove_dns_search; + nm_setting_ip6_config_clear_dns_searches; + nm_setting_ip6_config_get_num_addresses; + nm_setting_ip6_config_get_address; + nm_setting_ip6_config_add_address; + nm_setting_ip6_config_remove_address; + nm_setting_ip6_config_clear_addresses; + nm_setting_ip6_config_get_num_routes; + nm_setting_ip6_config_get_route; + nm_setting_ip6_config_add_route; + nm_setting_ip6_config_remove_route; + nm_setting_ip6_config_clear_routes; + nm_setting_ip6_config_get_ignore_auto_routes; + nm_setting_ip6_config_get_ignore_auto_dns; + nm_setting_ip6_config_get_never_default; + nm_setting_ip6_config_get_may_fail; + nm_setting_need_secrets; + nm_setting_ppp_error_get_type; + nm_setting_ppp_error_quark; + nm_setting_ppp_get_type; + nm_setting_ppp_new; + nm_setting_ppp_get_noauth; + nm_setting_ppp_get_refuse_eap; + nm_setting_ppp_get_refuse_pap; + nm_setting_ppp_get_refuse_chap; + nm_setting_ppp_get_refuse_mschap; + nm_setting_ppp_get_refuse_mschapv2; + nm_setting_ppp_get_nobsdcomp; + nm_setting_ppp_get_nodeflate; + nm_setting_ppp_get_no_vj_comp; + nm_setting_ppp_get_require_mppe; + nm_setting_ppp_get_require_mppe_128; + nm_setting_ppp_get_mppe_stateful; + nm_setting_ppp_get_crtscts; + nm_setting_ppp_get_baud; + nm_setting_ppp_get_mru; + nm_setting_ppp_get_mtu; + nm_setting_ppp_get_lcp_echo_failure; + nm_setting_ppp_get_lcp_echo_interval; + nm_setting_pppoe_error_get_type; + nm_setting_pppoe_error_quark; + nm_setting_pppoe_get_type; + nm_setting_pppoe_new; + nm_setting_pppoe_get_service; + nm_setting_pppoe_get_username; + nm_setting_pppoe_get_password; + nm_setting_serial_error_get_type; + nm_setting_serial_error_quark; + nm_setting_serial_get_type; + nm_setting_serial_new; + nm_setting_serial_get_baud; + nm_setting_serial_get_bits; + nm_setting_serial_get_parity; + nm_setting_serial_get_stopbits; + nm_setting_serial_get_send_delay; + nm_setting_to_hash; + nm_setting_to_string; + nm_setting_update_secrets; + nm_setting_verify; + nm_setting_vpn_error_get_type; + nm_setting_vpn_error_quark; + nm_setting_vpn_get_type; + nm_setting_vpn_new; + nm_setting_vpn_get_service_type; + nm_setting_vpn_get_user_name; + nm_setting_vpn_add_data_item; + nm_setting_vpn_foreach_data_item; + nm_setting_vpn_get_data_item; + nm_setting_vpn_remove_data_item; + nm_setting_vpn_add_secret; + nm_setting_vpn_foreach_secret; + nm_setting_vpn_get_secret; + nm_setting_vpn_remove_secret; + nm_setting_wired_error_get_type; + nm_setting_wired_error_quark; + nm_setting_wired_get_type; + nm_setting_wired_new; + nm_setting_wired_get_port; + nm_setting_wired_get_speed; + nm_setting_wired_get_duplex; + nm_setting_wired_get_auto_negotiate; + nm_setting_wired_get_mac_address; + nm_setting_wired_get_mtu; + nm_setting_wireless_ap_security_compatible; + nm_setting_wireless_error_get_type; + nm_setting_wireless_error_quark; + nm_setting_wireless_get_type; + nm_setting_wireless_new; + nm_setting_wireless_get_ssid; + nm_setting_wireless_get_mode; + nm_setting_wireless_get_band; + nm_setting_wireless_get_channel; + nm_setting_wireless_get_bssid; + nm_setting_wireless_get_rate; + nm_setting_wireless_get_tx_power; + nm_setting_wireless_get_mac_address; + nm_setting_wireless_get_mtu; + nm_setting_wireless_get_security; + nm_setting_wireless_add_seen_bssid; + nm_setting_wireless_get_num_seen_bssids; + nm_setting_wireless_get_seen_bssid; + nm_setting_wireless_security_add_proto; + nm_setting_wireless_security_add_pairwise; + nm_setting_wireless_security_add_group; + nm_setting_wireless_security_clear_groups; + nm_setting_wireless_security_clear_pairwise; + nm_setting_wireless_security_clear_protos; + nm_setting_wireless_security_error_get_type; + nm_setting_wireless_security_error_quark; + nm_setting_wireless_security_get_auth_alg; + nm_setting_wireless_security_get_group; + nm_setting_wireless_security_get_key_mgmt; + nm_setting_wireless_security_get_leap_username; + nm_setting_wireless_security_get_leap_password; + nm_setting_wireless_security_get_num_groups; + nm_setting_wireless_security_get_num_pairwise; + nm_setting_wireless_security_get_num_protos; + nm_setting_wireless_security_get_pairwise; + nm_setting_wireless_security_get_proto; + nm_setting_wireless_security_get_psk; + nm_setting_wireless_security_get_type; + nm_setting_wireless_security_get_wep_key; + nm_setting_wireless_security_get_wep_key_type; + nm_setting_wireless_security_get_wep_tx_keyidx; + nm_setting_wireless_security_new; + nm_setting_wireless_security_remove_group; + nm_setting_wireless_security_remove_pairwise; + nm_setting_wireless_security_remove_proto; + nm_setting_wireless_security_set_wep_key; + nm_setting_olpc_mesh_error_quark; + nm_setting_olpc_mesh_error_get_type; + nm_setting_olpc_mesh_get_type; + nm_setting_olpc_mesh_get_ssid; + nm_setting_olpc_mesh_get_channel; + nm_setting_olpc_mesh_get_dhcp_anycast_address; + nm_setting_olpc_mesh_new; + nm_utils_deinit; + nm_utils_rsa_key_encrypt; + nm_utils_escape_ssid; + nm_utils_gvalue_hash_dup; + nm_utils_init; + nm_utils_ip4_addresses_from_gvalue; + nm_utils_ip4_addresses_to_gvalue; + nm_utils_ip4_netmask_to_prefix; + nm_utils_ip4_prefix_to_netmask; + nm_utils_ip4_get_default_prefix; + nm_utils_ip4_routes_from_gvalue; + nm_utils_ip4_routes_to_gvalue; + nm_utils_ip6_addresses_from_gvalue; + nm_utils_ip6_addresses_to_gvalue; + nm_utils_ip6_routes_from_gvalue; + nm_utils_ip6_routes_to_gvalue; + nm_utils_is_empty_ssid; + nm_utils_same_ssid; + nm_utils_security_valid; + nm_utils_slist_free; + nm_utils_ssid_to_utf8; + nm_utils_uuid_generate; + nm_utils_uuid_generate_from_string; + nm_ip4_address_compare; + nm_ip4_address_dup; + nm_ip4_address_get_address; + nm_ip4_address_get_prefix; + nm_ip4_address_get_gateway; + nm_ip4_address_new; + nm_ip4_address_ref; + nm_ip4_address_set_address; + nm_ip4_address_set_prefix; + nm_ip4_address_set_gateway; + nm_ip4_address_unref; + nm_ip4_route_compare; + nm_ip4_route_dup; + nm_ip4_route_get_dest; + nm_ip4_route_get_prefix; + nm_ip4_route_get_next_hop; + nm_ip4_route_get_metric; + nm_ip4_route_new; + nm_ip4_route_ref; + nm_ip4_route_unref; + nm_ip4_route_set_dest; + nm_ip4_route_set_prefix; + nm_ip4_route_set_next_hop; + nm_ip4_route_set_metric; +local: + *; +}; diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c new file mode 100644 index 00000000..d9cdc270 --- /dev/null +++ b/libnm-util/nm-connection.c @@ -0,0 +1,1210 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2009 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <glib-object.h> +#include <dbus/dbus-glib.h> +#include <string.h> +#include "nm-connection.h" +#include "nm-utils.h" +#include "nm-utils-private.h" + +#include "nm-setting-8021x.h" +#include "nm-setting-bluetooth.h" +#include "nm-setting-connection.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-setting-ppp.h" +#include "nm-setting-pppoe.h" +#include "nm-setting-wired.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wireless-security.h" +#include "nm-setting-vpn.h" +#include "nm-setting-olpc-mesh.h" + +#include "nm-setting-serial.h" +#include "nm-setting-gsm.h" +#include "nm-setting-cdma.h" + +/** + * SECTION:nm-connection + * @short_description: Describes a connection to specific network or provider + * @include: nm-connection.h + * + * An #NMConnection describes all the settings and configuration values that + * are necessary to configure network devices for operation on a specific + * network. Connections are the fundamental operating object for + * NetworkManager; no device is connected without a #NMConnection, or + * disconnected without having been connected with a #NMConnection. + * + * Each #NMConnection contains a list of #NMSetting objects usually referenced + * by name (using nm_connection_get_setting_by_name()) or by type (with + * nm_connection_get_setting()). The settings describe the actual parameters + * with which the network devices are configured, including device-specific + * parameters (MTU, SSID, APN, channel, rate, etc) and IP-level parameters + * (addresses, routes, addressing methods, etc). + * + * Most connections also have a %NMConnectionScope; a connection will be + * provided over D-Bus either by the user settings service + * (org.freedesktop.NetworkManagerUserSettings) running in an active user + * session, or by the system-wide system settings service + * (org.freedesktop.NetworkManagerSystemSettings) which provides connections + * for all users. + */ + +/** + * nm_connection_error_quark: + * + * Registers an error quark for #NMConnection if necessary. + * + * Returns: the error quark used for #NMConnection errors. + **/ +GQuark +nm_connection_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-connection-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_connection_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + ENUM_ENTRY (NM_CONNECTION_ERROR_UNKNOWN, "UnknownError"), + ENUM_ENTRY (NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND, "ConnectionSettingNotFound"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMConnectionError", values); + } + return etype; +} + +typedef struct { + GHashTable *settings; + + /* Type of the connection (system or user) */ + NMConnectionScope scope; + + /* D-Bus path of the connection, if any */ + char *path; +} NMConnectionPrivate; + +#define NM_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONNECTION, NMConnectionPrivate)) + +G_DEFINE_TYPE (NMConnection, nm_connection, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_SCOPE, + PROP_PATH, + + LAST_PROP +}; + +enum { + SECRETS_UPDATED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static GHashTable *registered_settings = NULL; + +#define DEFAULT_MAP_SIZE 15 + +static struct SettingInfo { + const char *name; + GType type; + guint32 priority; + GQuark error_quark; +} default_map[DEFAULT_MAP_SIZE] = { { NULL } }; + +static void +setting_register (const char *name, GType type) +{ + g_return_if_fail (name != NULL); + g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (type)); + + if (G_UNLIKELY (!registered_settings)) { + registered_settings = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + } + + if (g_hash_table_lookup (registered_settings, name)) + g_warning ("Already have a creator function for '%s', overriding", name); + + g_hash_table_insert (registered_settings, g_strdup (name), g_strdup (g_type_name (type))); +} + +#if UNUSED +static void +setting_unregister (const char *name) +{ + if (registered_settings) + g_hash_table_remove (registered_settings, name); +} +#endif + +static void +register_one_setting (const char *name, GType type, GQuark error_quark, guint32 priority) +{ + static guint32 i = 0; + + g_return_if_fail (i < DEFAULT_MAP_SIZE); + g_return_if_fail (default_map[i].name == NULL); + + default_map[i].name = name; + default_map[i].type = type; + default_map[i].error_quark = error_quark; + default_map[i].priority = priority; + i++; + + setting_register (name, type); +} + +static void +register_default_settings (void) +{ + _nm_utils_register_value_transformations (); + + if (G_LIKELY (default_map[0].name)) + return; + + register_one_setting (NM_SETTING_CONNECTION_SETTING_NAME, + NM_TYPE_SETTING_CONNECTION, + NM_SETTING_CONNECTION_ERROR, + 0); + + register_one_setting (NM_SETTING_WIRED_SETTING_NAME, + NM_TYPE_SETTING_WIRED, + NM_SETTING_WIRED_ERROR, + 1); + + register_one_setting (NM_SETTING_WIRELESS_SETTING_NAME, + NM_TYPE_SETTING_WIRELESS, + NM_SETTING_WIRELESS_ERROR, + 1); + + register_one_setting (NM_SETTING_OLPC_MESH_SETTING_NAME, + NM_TYPE_SETTING_OLPC_MESH, + NM_SETTING_OLPC_MESH_ERROR, + 1); + + register_one_setting (NM_SETTING_GSM_SETTING_NAME, + NM_TYPE_SETTING_GSM, + NM_SETTING_GSM_ERROR, + 1); + + register_one_setting (NM_SETTING_CDMA_SETTING_NAME, + NM_TYPE_SETTING_CDMA, + NM_SETTING_CDMA_ERROR, + 1); + + register_one_setting (NM_SETTING_BLUETOOTH_SETTING_NAME, + NM_TYPE_SETTING_BLUETOOTH, + NM_SETTING_BLUETOOTH_ERROR, + 1); + + register_one_setting (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_TYPE_SETTING_WIRELESS_SECURITY, + NM_SETTING_WIRELESS_SECURITY_ERROR, + 2); + + register_one_setting (NM_SETTING_SERIAL_SETTING_NAME, + NM_TYPE_SETTING_SERIAL, + NM_SETTING_SERIAL_ERROR, + 2); + + register_one_setting (NM_SETTING_PPP_SETTING_NAME, + NM_TYPE_SETTING_PPP, + NM_SETTING_PPP_ERROR, + 3); + + register_one_setting (NM_SETTING_PPPOE_SETTING_NAME, + NM_TYPE_SETTING_PPPOE, + NM_SETTING_PPPOE_ERROR, + 3); + + register_one_setting (NM_SETTING_802_1X_SETTING_NAME, + NM_TYPE_SETTING_802_1X, + NM_SETTING_802_1X_ERROR, + 3); + + register_one_setting (NM_SETTING_VPN_SETTING_NAME, + NM_TYPE_SETTING_VPN, + NM_SETTING_VPN_ERROR, + 4); + + register_one_setting (NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_TYPE_SETTING_IP4_CONFIG, + NM_SETTING_IP4_CONFIG_ERROR, + 6); + + register_one_setting (NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_TYPE_SETTING_IP6_CONFIG, + NM_SETTING_IP6_CONFIG_ERROR, + 6); + + /* Be sure to update DEFAULT_MAP_SIZE if you add another setting!! */ +} + +static guint32 +get_priority_for_setting_type (GType type) +{ + int i; + + for (i = 0; default_map[i].name; i++) { + if (default_map[i].type == type) + return default_map[i].priority; + } + + return G_MAXUINT32; +} + +/** + * nm_connection_lookup_setting_type: + * @name: a setting name + * + * Returns the #GType of the setting's class for a given setting name. + * + * Returns: the #GType of the setting's class + **/ +GType +nm_connection_lookup_setting_type (const char *name) +{ + char *type_name; + GType type; + + g_return_val_if_fail (name != NULL, G_TYPE_NONE); + + if (!registered_settings) + register_default_settings (); + + type_name = (char *) g_hash_table_lookup (registered_settings, name); + if (type_name) { + type = g_type_from_name (type_name); + if (!type) + g_warning ("Can not get type for '%s'.", type_name); + } else { + type = 0; + g_warning ("Unknown setting '%s'", name); + } + + return type; +} + +/** + * nm_connection_lookup_setting_type_by_quark: + * @error_quark: a setting error quark + * + * Returns the #GType of the setting's class for a given setting error quark. + * Useful for figuring out which setting a returned error is for. + * + * Returns: the #GType of the setting's class + **/ +GType +nm_connection_lookup_setting_type_by_quark (GQuark error_quark) +{ + int i; + + for (i = 0; default_map[i].name; i++) { + if (default_map[i].error_quark == error_quark) + return default_map[i].type; + } + + return G_TYPE_INVALID; +} + +/** + * nm_connection_create_setting: + * @name: a setting name + * + * Create a new #NMSetting object of the desired type, given a setting name. + * + * Returns: the new setting object, or NULL if the setting name was unknown + **/ +NMSetting * +nm_connection_create_setting (const char *name) +{ + GType type; + NMSetting *setting = NULL; + + g_return_val_if_fail (name != NULL, NULL); + + type = nm_connection_lookup_setting_type (name); + if (type) + setting = (NMSetting *) g_object_new (type, NULL); + + return setting; +} + +static void +parse_one_setting (gpointer key, gpointer value, gpointer user_data) +{ + NMConnection *connection = (NMConnection *) user_data; + GType type; + NMSetting *setting = NULL; + + type = nm_connection_lookup_setting_type ((char *) key); + if (type) + setting = nm_setting_new_from_hash (type, (GHashTable *) value); + if (setting) + nm_connection_add_setting (connection, setting); +} + +/** + * nm_connection_add_setting: + * @connection: a #NMConnection + * @setting: the #NMSetting to add to the connection object + * + * Adds a #NMSetting to the connection, replacing any previous #NMSetting of the + * same name which has previously been added to the #NMConnection. The + * connection takes ownership of the #NMSetting object and does not increase + * the setting object's reference count. + **/ +void +nm_connection_add_setting (NMConnection *connection, NMSetting *setting) +{ + g_return_if_fail (NM_IS_CONNECTION (connection)); + g_return_if_fail (NM_IS_SETTING (setting)); + + g_hash_table_insert (NM_CONNECTION_GET_PRIVATE (connection)->settings, + g_strdup (G_OBJECT_TYPE_NAME (setting)), setting); +} + +/** + * nm_connection_remove_setting: + * @connection: a #NMConnection + * @setting_type: the #GType of the setting object to remove + * + * Removes the #NMSetting with the given #GType from the #NMConnection. This + * operation dereferences the #NMSetting object. + **/ +void +nm_connection_remove_setting (NMConnection *connection, GType setting_type) +{ + g_return_if_fail (NM_IS_CONNECTION (connection)); + g_return_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING)); + + g_hash_table_remove (NM_CONNECTION_GET_PRIVATE (connection)->settings, g_type_name (setting_type)); +} + +/** + * nm_connection_get_setting: + * @connection: a #NMConnection + * @setting_type: the #GType of the setting object to return + * + * Gets the #NMSetting with the given #GType, if one has been previously added + * to the #NMConnection. + * + * Returns: the #NMSetting, or NULL if no setting of that type was previously + * added to the #NMConnection + **/ +NMSetting * +nm_connection_get_setting (NMConnection *connection, GType setting_type) +{ + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING), NULL); + + return (NMSetting *) g_hash_table_lookup (NM_CONNECTION_GET_PRIVATE (connection)->settings, + g_type_name (setting_type)); +} + +/** + * nm_connection_get_setting_by_name: + * @connection: a #NMConnection + * @name: a setting name + * + * Gets the #NMSetting with the given name, if one has been previously added + * the the #NMConnection. + * + * Returns: the #NMSetting, or NULL if no setting with that name was previously + * added to the #NMConnection + **/ +NMSetting * +nm_connection_get_setting_by_name (NMConnection *connection, const char *name) +{ + GType type; + + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (name != NULL, NULL); + + type = nm_connection_lookup_setting_type (name); + + return type ? nm_connection_get_setting (connection, type) : NULL; +} + +/** + * nm_connection_replace_settings: + * @connection: a #NMConnection + * @new_settings: a #GHashTable of settings + * @error: location to store error, or %NULL + * + * Returns: %TRUE if the settings were valid and added to the connection, %FALSE + * if they were not + **/ +gboolean +nm_connection_replace_settings (NMConnection *connection, + GHashTable *new_settings, + GError **error) +{ + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + g_return_val_if_fail (new_settings != NULL, FALSE); + if (error) + g_return_val_if_fail (*error == NULL, FALSE); + + g_hash_table_remove_all (NM_CONNECTION_GET_PRIVATE (connection)->settings); + g_hash_table_foreach (new_settings, parse_one_setting, connection); + + return nm_connection_verify (connection, error); +} + +typedef struct { + NMConnection *other; + gboolean failed; + NMSettingCompareFlags flags; +} CompareConnectionInfo; + +static void +compare_one_setting (gpointer key, gpointer value, gpointer user_data) +{ + NMSetting *setting = (NMSetting *) value; + CompareConnectionInfo *info = (CompareConnectionInfo *) user_data; + NMSetting *other_setting; + + if (info->failed) + return; + + other_setting = nm_connection_get_setting (info->other, G_OBJECT_TYPE (setting)); + if (other_setting) + info->failed = nm_setting_compare (setting, other_setting, info->flags) ? FALSE : TRUE; + else + info->failed = TRUE; +} + +/** + * nm_connection_compare: + * @a: a #NMConnection + * @b: a second #NMConnection to compare with the first + * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT + * + * Compares two #NMConnection objects for similarity, with comparison behavior + * modified by a set of flags. See nm_setting_compare() for a description of + * each flag's behavior. + * + * Returns: %TRUE if the comparison succeeds, %FALSE if it does not + **/ +gboolean +nm_connection_compare (NMConnection *a, + NMConnection *b, + NMSettingCompareFlags flags) +{ + NMConnectionPrivate *priv; + CompareConnectionInfo info = { b, FALSE, flags }; + + if (!a && !b) + return TRUE; + + if (!a || !b) + return FALSE; + + priv = NM_CONNECTION_GET_PRIVATE (a); + g_hash_table_foreach (priv->settings, compare_one_setting, &info); + if (info.failed == FALSE) { + /* compare A to B, then if that is the same compare B to A to ensure + * that keys that are in B but not A will make the comparison fail. + */ + info.failed = FALSE; + info.other = a; + priv = NM_CONNECTION_GET_PRIVATE (b); + g_hash_table_foreach (priv->settings, compare_one_setting, &info); + } + + return info.failed ? FALSE : TRUE; +} + +typedef struct { + gboolean success; + GSList *all_settings; + GError **error; +} VerifySettingsInfo; + +static void +verify_one_setting (gpointer data, gpointer user_data) +{ + NMSetting *setting = NM_SETTING (data); + VerifySettingsInfo *info = (VerifySettingsInfo *) user_data; + + if (info->success) + info->success = nm_setting_verify (setting, info->all_settings, info->error); +} + +static void +hash_values_to_slist (gpointer key, gpointer value, gpointer user_data) +{ + GSList **list = (GSList **) user_data; + + *list = g_slist_prepend (*list, value); +} + +/** + * nm_connection_verify: + * @connection: the #NMConnection to verify + * @error: location to store error, or %NULL + * + * Validates the connection and all its settings. Each setting's properties + * have allowed values, and some values are dependent on other values. For + * example, if a WiFi connection is security enabled, the #NMSettingWireless + * setting object's 'security' property must contain the setting name of the + * #NMSettingWirelessSecurity object, which must also be present in the + * connection for the connection to be valid. As another example, the + * #NMSettingWired object's 'mac-address' property must be a validly formatted + * MAC address. The returned #GError contains information about which + * setting and which property failed validation, and how it failed validation. + * + * Returns: %TRUE if the connection is valid, %FALSE if it is not + **/ +gboolean +nm_connection_verify (NMConnection *connection, GError **error) +{ + NMConnectionPrivate *priv; + NMSetting *s_con; + VerifySettingsInfo info; + + if (error) + g_return_val_if_fail (*error == NULL, FALSE); + + if (!NM_IS_CONNECTION (connection)) { + g_set_error (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_UNKNOWN, + "invalid connection; failed verification"); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + } + + priv = NM_CONNECTION_GET_PRIVATE (connection); + + /* First, make sure there's at least 'connection' setting */ + s_con = nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + if (!s_con) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND, + "connection setting not found"); + return FALSE; + } + + /* Now, run the verify function of each setting */ + memset (&info, 0, sizeof (info)); + info.success = TRUE; + info.error = error; + g_hash_table_foreach (priv->settings, hash_values_to_slist, &info.all_settings); + + g_slist_foreach (info.all_settings, verify_one_setting, &info); + g_slist_free (info.all_settings); + return info.success; +} + +/** + * nm_connection_update_secrets: + * @connection: the #NMConnection + * @setting_name: the setting object name to which the secrets apply + * @secrets: a #GHashTable mapping string:#GValue of setting property names and + * secrets + * @error: location to store error, or %NULL + * + * Update the specified setting's secrets, given a hash table of secrets + * intended for that setting (deserialized from D-Bus for example). + * + * Returns: %TRUE if the secrets were successfully updated and the connection + * is valid, %FALSE on failure or if the setting was never added to the connection + **/ +gboolean +nm_connection_update_secrets (NMConnection *connection, + const char *setting_name, + GHashTable *secrets, + GError **error) +{ + NMSetting *setting; + gboolean success; + + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + g_return_val_if_fail (setting_name != NULL, FALSE); + g_return_val_if_fail (secrets != NULL, FALSE); + if (error) + g_return_val_if_fail (*error == NULL, FALSE); + + setting = nm_connection_get_setting (connection, nm_connection_lookup_setting_type (setting_name)); + if (!setting) { + g_set_error (error, NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND, + "%s", setting_name); + return FALSE; + } + + success = nm_setting_update_secrets (setting, secrets, error); + if (success) + g_signal_emit (connection, signals[SECRETS_UPDATED], 0, setting_name); + return success; +} + +static gint +setting_priority_compare (gconstpointer a, gconstpointer b) +{ + guint32 prio_a, prio_b; + + prio_a = get_priority_for_setting_type (G_OBJECT_TYPE (NM_SETTING (a))); + prio_b = get_priority_for_setting_type (G_OBJECT_TYPE (NM_SETTING (b))); + + if (prio_a < prio_b) + return -1; + else if (prio_a == prio_b) + return 0; + return 1; +} + +static void +add_setting_to_list (gpointer key, gpointer data, gpointer user_data) +{ + GSList **list = (GSList **) user_data; + + *list = g_slist_insert_sorted (*list, NM_SETTING (data), setting_priority_compare); +} + +/** + * nm_connection_need_secrets: + * @connection: the #NMConnection + * @hints: the address of a pointer to a #GPtrArray, initialized to NULL, which + * on return points to an allocated #GPtrArray containing the property names of + * secrets of the #NMSetting which may be required; the caller owns the array + * and must free the each array element with g_free(), as well as the array + * itself with g_ptr_array_free() + * + * Returns the name of the first setting object in the connection which would + * need secrets to make a successful connection. The returned hints are only + * intended as a guide to what secrets may be required, because in some + * circumstances, there is no way to conclusively determine exactly which + * secrets are needed. + * + * Returns: the setting name of the #NMSetting object which has invalid or + * missing secrets + **/ +const char * +nm_connection_need_secrets (NMConnection *connection, + GPtrArray **hints) +{ + NMConnectionPrivate *priv; + GSList *settings = NULL; + GSList *iter; + char *name = NULL; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + if (hints) + g_return_val_if_fail (*hints == NULL, NULL); + + priv = NM_CONNECTION_GET_PRIVATE (connection); + + /* Get list of settings in priority order */ + g_hash_table_foreach (priv->settings, add_setting_to_list, &settings); + + for (iter = settings; iter; iter = g_slist_next (iter)) { + NMSetting *setting = NM_SETTING (iter->data); + GPtrArray *secrets; + + // FIXME: do something with requested secrets rather than asking for + // all of them. Maybe make secrets a hash table mapping + // settings name :: [list of secrets key names]. + secrets = nm_setting_need_secrets (setting); + if (secrets) { + if (hints) + *hints = secrets; + else + g_ptr_array_free (secrets, TRUE); + + name = (char *) nm_setting_get_name (setting); + break; + } + } + + g_slist_free (settings); + return name; +} + +static void +clear_setting_secrets (gpointer key, gpointer data, gpointer user_data) +{ + nm_setting_clear_secrets (NM_SETTING (data)); +} + +/** + * nm_connection_clear_secrets: + * @connection: the #NMConnection + * + * Clears and frees any secrets that may be stored in the connection, to avoid + * keeping secret data in memory when not needed. + **/ +void +nm_connection_clear_secrets (NMConnection *connection) +{ + NMConnectionPrivate *priv; + + g_return_if_fail (NM_IS_CONNECTION (connection)); + + priv = NM_CONNECTION_GET_PRIVATE (connection); + g_hash_table_foreach (priv->settings, clear_setting_secrets, NULL); +} + +static void +add_one_setting_to_hash (gpointer key, gpointer data, gpointer user_data) +{ + NMSetting *setting = (NMSetting *) data; + GHashTable *connection_hash = (GHashTable *) user_data; + GHashTable *setting_hash; + + g_return_if_fail (setting != NULL); + g_return_if_fail (connection_hash != NULL); + + setting_hash = nm_setting_to_hash (setting); + if (setting_hash) + g_hash_table_insert (connection_hash, + g_strdup (nm_setting_get_name (setting)), + setting_hash); +} + +/** + * nm_connection_to_hash: + * @connection: the #NMConnection + * + * Converts the #NMConnection into a #GHashTable describing the connection, + * suitable for marshalling over D-Bus or serializing. The hash table mapping + * is string:#GHashTable with each element in the returned hash representing + * a #NMSetting object. The keys are setting object names, and the values + * are #GHashTables mapping string:GValue, each of which represents the + * properties of the #NMSetting object. + * + * Returns: a new #GHashTable describing the connection, its settings, and + * each setting's properties. The caller owns the hash table and must unref + * the hash table with g_hash_table_unref() when it is no longer needed. + **/ +GHashTable * +nm_connection_to_hash (NMConnection *connection) +{ + NMConnectionPrivate *priv; + GHashTable *connection_hash; + + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + + connection_hash = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) g_hash_table_destroy); + + priv = NM_CONNECTION_GET_PRIVATE (connection); + g_hash_table_foreach (priv->settings, add_one_setting_to_hash, connection_hash); + + /* Don't send empty hashes */ + if (g_hash_table_size (connection_hash) < 1) { + g_hash_table_destroy (connection_hash); + connection_hash = NULL; + } + + return connection_hash; +} + +typedef struct ForEachValueInfo { + NMSettingValueIterFn func; + gpointer user_data; +} ForEachValueInfo; + +static void +for_each_setting (gpointer key, gpointer value, gpointer user_data) +{ + ForEachValueInfo *info = (ForEachValueInfo *) user_data; + + nm_setting_enumerate_values (NM_SETTING (value), info->func, info->user_data); +} + +/** + * nm_connection_for_each_setting_value: + * @connection: the #NMConnection + * @func: user-supplied function called for each setting's property + * @user_data: user data passed to @func at each invocation + * + * Iterates over the properties of each #NMSetting object in the #NMConnection, + * calling the supplied user function for each property. + **/ +void +nm_connection_for_each_setting_value (NMConnection *connection, + NMSettingValueIterFn func, + gpointer user_data) +{ + NMConnectionPrivate *priv; + ForEachValueInfo *info; + + g_return_if_fail (NM_IS_CONNECTION (connection)); + g_return_if_fail (func != NULL); + + priv = NM_CONNECTION_GET_PRIVATE (connection); + + info = g_slice_new0 (ForEachValueInfo); + if (!info) { + g_warning ("Not enough memory to enumerate values."); + return; + } + info->func = func; + info->user_data = user_data; + + g_hash_table_foreach (priv->settings, for_each_setting, info); + + g_slice_free (ForEachValueInfo, info); +} + +static void +dump_setting (gpointer key, gpointer value, gpointer user_data) +{ + char *str; + + str = nm_setting_to_string (NM_SETTING (value)); + g_print ("%s\n", str); + g_free (str); +} + +/** + * nm_connection_dump: + * @connection: the #NMConnection + * + * Print the connection to stdout. For debugging purposes ONLY, should NOT + * be used for serialization of the connection or machine-parsed in any way. The + * output format is not guaranteed to be stable and may change at any time. + **/ +void +nm_connection_dump (NMConnection *connection) +{ + g_return_if_fail (NM_IS_CONNECTION (connection)); + + g_hash_table_foreach (NM_CONNECTION_GET_PRIVATE (connection)->settings, dump_setting, NULL); +} + +/** + * nm_connection_set_scope: + * @connection: the #NMConnection + * @scope: the scope of the connection + * + * Sets the scope of the connection. This property is not serialized, and is + * only for the reference of the caller. A connection may have no scope + * (internal, temporary connections), "system" scope (provided by the system + * settings service), or "user" scope, provided by a user settings service. The + * creator of the #NMConnection object is responsible for setting the + * connection's scope if needed. Sets the #NMConnection:scope property. + **/ +void +nm_connection_set_scope (NMConnection *connection, NMConnectionScope scope) +{ + g_return_if_fail (NM_IS_CONNECTION (connection)); + + NM_CONNECTION_GET_PRIVATE (connection)->scope = scope; +} + +/** + * nm_connection_get_scope: + * @connection: the #NMConnection + * + * Returns the connection scope. + * + * Returns: the scope of the connection, previously set by a call to + * nm_connection_set_scope(). + **/ +NMConnectionScope +nm_connection_get_scope (NMConnection *connection) +{ + g_return_val_if_fail (NM_IS_CONNECTION (connection), NM_CONNECTION_SCOPE_UNKNOWN); + + return NM_CONNECTION_GET_PRIVATE (connection)->scope; +} + +/** + * nm_connection_set_path: + * @connection: the #NMConnection + * @path: the D-Bus path of the connection as given by the settings service + * which provides the connection + * + * Sets the D-Bus path of the connection. This property is not serialized, and + * is only for the reference of the caller. Sets the #NMConnection:path + * property. + **/ +void +nm_connection_set_path (NMConnection *connection, const char *path) +{ + NMConnectionPrivate *priv; + + g_return_if_fail (NM_IS_CONNECTION (connection)); + + priv = NM_CONNECTION_GET_PRIVATE (connection); + + if (priv->path) { + g_free (priv->path); + priv->path = NULL; + } + + if (path) + priv->path = g_strdup (path); +} + +/** + * nm_connection_get_path: + * @connection: the #NMConnection + * + * Returns the connection's D-Bus path. + * + * Returns: the D-Bus path of the connection, previously set by a call to + * nm_connection_set_path(). + **/ +const char * +nm_connection_get_path (NMConnection *connection) +{ + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + + return NM_CONNECTION_GET_PRIVATE (connection)->path; +} + +/** + * nm_connection_new: + * + * Creates a new #NMConnection object with no #NMSetting objects. + * + * Returns: the new empty #NMConnection object + **/ +NMConnection * +nm_connection_new (void) +{ + GObject *object; + + if (!registered_settings) + register_default_settings (); + + object = g_object_new (NM_TYPE_CONNECTION, NULL); + + return NM_CONNECTION (object); +} + +/** + * nm_connection_new_from_hash: + * @hash: the #GHashTable describing the connection + * @error: on unsuccessful return, an error + * + * Creates a new #NMConnection from a hash table describing the connection. See + * nm_connection_to_hash() for a description of the expected hash table. + * + * Returns: the new #NMConnection object, populated with settings created + * from the values in the hash table, or NULL if the connection failed to + * validate + **/ +NMConnection * +nm_connection_new_from_hash (GHashTable *hash, GError **error) +{ + NMConnection *connection; + + g_return_val_if_fail (hash != NULL, NULL); + + connection = nm_connection_new (); + g_hash_table_foreach (hash, parse_one_setting, connection); + + if (!nm_connection_verify (connection, error)) { + g_object_unref (connection); + return NULL; + } + + return connection; +} + +static void +duplicate_cb (gpointer key, gpointer value, gpointer user_data) +{ + nm_connection_add_setting (NM_CONNECTION (user_data), nm_setting_duplicate (NM_SETTING (value))); +} + +/** + * nm_connection_duplicate: + * @connection: the #NMConnection to duplicate + * + * Duplicates a #NMConnection. + * + * Returns: a new #NMConnection containing the same settings and properties + * as the source #NMConnection + **/ +NMConnection * +nm_connection_duplicate (NMConnection *connection) +{ + NMConnection *dup; + + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + + dup = nm_connection_new (); + nm_connection_set_scope (dup, nm_connection_get_scope (connection)); + nm_connection_set_path (dup, nm_connection_get_path (connection)); + g_hash_table_foreach (NM_CONNECTION_GET_PRIVATE (connection)->settings, duplicate_cb, dup); + + return dup; +} + +static void +nm_connection_init (NMConnection *connection) +{ + NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection); + + priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); +} + +static void +finalize (GObject *object) +{ + NMConnection *connection = NM_CONNECTION (object); + NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection); + + g_hash_table_destroy (priv->settings); + priv->settings = NULL; + + g_free (priv->path); + priv->path = NULL; + + G_OBJECT_CLASS (nm_connection_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMConnection *connection = NM_CONNECTION (object); + + switch (prop_id) { + case PROP_SCOPE: + nm_connection_set_scope (connection, g_value_get_uint (value)); + break; + case PROP_PATH: + nm_connection_set_path (connection, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMConnection *connection = NM_CONNECTION (object); + + switch (prop_id) { + case PROP_SCOPE: + g_value_set_uint (value, nm_connection_get_scope (connection)); + break; + case PROP_PATH: + g_value_set_string (value, nm_connection_get_path (connection)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_connection_class_init (NMConnectionClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMConnectionPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + /* Properties */ + + /** + * NMConnection:scope: + * + * The connection's scope, used only by the calling process as a record + * of which settings service the connection is provided by. One of the + * NM_CONNECTION_SCOPE_* defines. + **/ + g_object_class_install_property + (object_class, PROP_SCOPE, + g_param_spec_uint (NM_CONNECTION_SCOPE, + "Scope", + "Scope", + NM_CONNECTION_SCOPE_UNKNOWN, + NM_CONNECTION_SCOPE_USER, + NM_CONNECTION_SCOPE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /** + * NMConnection:path: + * + * The connection's D-Bus path, used only by the calling process as a record + * of the D-Bus path of the connection as provided by a settings service. + **/ + g_object_class_install_property + (object_class, PROP_PATH, + g_param_spec_string (NM_CONNECTION_PATH, + "Path", + "Path", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /* Signals */ + + /** + * NMConnection::secrets-updated: + * @connection: the object on which the signal is emitted + * @setting_name: the setting name of the #NMSetting for which secrets were + * updated + * + * The ::secrets-updated signal is emitted when the secrets of a setting + * have been changed. + */ + signals[SECRETS_UPDATED] = + g_signal_new ("secrets-updated", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMConnectionClass, secrets_updated), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); +} + diff --git a/libnm-util/nm-connection.h b/libnm-util/nm-connection.h new file mode 100644 index 00000000..576db049 --- /dev/null +++ b/libnm-util/nm-connection.h @@ -0,0 +1,167 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_CONNECTION_H +#define NM_CONNECTION_H + +#include <glib.h> +#include <glib-object.h> +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_CONNECTION (nm_connection_get_type ()) +#define NM_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONNECTION, NMConnection)) +#define NM_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CONNECTION, NMConnectionClass)) +#define NM_IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CONNECTION)) +#define NM_IS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_CONNECTION)) +#define NM_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONNECTION, NMConnectionClass)) + +/** + * NMConnectionScope: + * @NM_CONNECTION_SCOPE_UNKNOWN: scope not known or not yet set + * @NM_CONNECTION_SCOPE_SYSTEM: connection is provided by the system settings + * service + * @NM_CONNECTION_SCOPE_USER: connection is provided by a user settings service + * + * Connection scope indicated what settings service, if any, provides the + * connection. + * + **/ +typedef enum { + NM_CONNECTION_SCOPE_UNKNOWN = 0, + NM_CONNECTION_SCOPE_SYSTEM, + NM_CONNECTION_SCOPE_USER +} NMConnectionScope; + + +/** + * NMConnectionError: + * @NM_CONNECTION_ERROR_UNKNOWN: unknown or unclassified error + * @NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND: the #NMConnection object + * did not contain the required #NMSettingConnection object, which must be + * present for all connections + * + * Describes errors that may result from operations involving a #NMConnection. + * + **/ +typedef enum +{ + NM_CONNECTION_ERROR_UNKNOWN = 0, + NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND +} NMConnectionError; + +#define NM_TYPE_CONNECTION_ERROR (nm_connection_error_get_type ()) +GType nm_connection_error_get_type (void); + +#define NM_CONNECTION_ERROR nm_connection_error_quark () +GQuark nm_connection_error_quark (void); + +#define NM_CONNECTION_SCOPE "scope" +#define NM_CONNECTION_PATH "path" + +/** + * NMConnection: + * + * The NMConnection struct contains only private data. + * It should only be accessed through the functions described below. + */ +typedef struct { + GObject parent; +} NMConnection; + +typedef struct { + GObjectClass parent; + + /* Signals */ + void (*secrets_updated) (NMConnection *connection, const char * setting); +} NMConnectionClass; + +GType nm_connection_get_type (void); + +NMConnection *nm_connection_new (void); + +NMConnection *nm_connection_new_from_hash (GHashTable *hash, GError **error); + +NMConnection *nm_connection_duplicate (NMConnection *connection); + +void nm_connection_add_setting (NMConnection *connection, + NMSetting *setting); + +void nm_connection_remove_setting (NMConnection *connection, + GType setting_type); + +NMSetting *nm_connection_get_setting (NMConnection *connection, + GType setting_type); + +NMSetting *nm_connection_get_setting_by_name (NMConnection *connection, + const char *name); + +gboolean nm_connection_replace_settings (NMConnection *connection, + GHashTable *new_settings, + GError **error); + +gboolean nm_connection_compare (NMConnection *a, + NMConnection *b, + NMSettingCompareFlags flags); + +gboolean nm_connection_verify (NMConnection *connection, GError **error); + +const char * nm_connection_need_secrets (NMConnection *connection, + GPtrArray **hints); + +void nm_connection_clear_secrets (NMConnection *connection); + +gboolean nm_connection_update_secrets (NMConnection *connection, + const char *setting_name, + GHashTable *secrets, + GError **error); + +void nm_connection_set_scope (NMConnection *connection, + NMConnectionScope scope); + +NMConnectionScope nm_connection_get_scope (NMConnection *connection); + +void nm_connection_set_path (NMConnection *connection, + const char *path); + +const char * nm_connection_get_path (NMConnection *connection); + +void nm_connection_for_each_setting_value (NMConnection *connection, + NMSettingValueIterFn func, + gpointer user_data); + +GHashTable *nm_connection_to_hash (NMConnection *connection); +void nm_connection_dump (NMConnection *connection); + +NMSetting *nm_connection_create_setting (const char *name); + +GType nm_connection_lookup_setting_type (const char *name); + +GType nm_connection_lookup_setting_type_by_quark (GQuark error_quark); + +G_END_DECLS + +#endif /* NM_CONNECTION_H */ diff --git a/libnm-util/nm-param-spec-specialized.c b/libnm-util/nm-param-spec-specialized.c new file mode 100644 index 00000000..f5a362ce --- /dev/null +++ b/libnm-util/nm-param-spec-specialized.c @@ -0,0 +1,973 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2010 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include "nm-param-spec-specialized.h" + +struct _NMParamSpecSpecialized { + GParamSpec parent; +}; + +#include <string.h> +#include <math.h> +#include <netinet/in.h> +#include <dbus/dbus-glib.h> + +#include "nm-dbus-glib-types.h" + +/***********************************************************/ +/* nm_gvalues_compare */ + +static gint nm_gvalues_compare (const GValue *value1, const GValue *value2); + +static gboolean +type_is_fixed_size (GType type, gsize *tsize) +{ + switch (type) { + case G_TYPE_CHAR: + if (tsize) *tsize = sizeof (char); + return TRUE; + case G_TYPE_UCHAR: + if (tsize) *tsize = sizeof (guchar); + return TRUE; + case G_TYPE_BOOLEAN: + if (tsize) *tsize = sizeof (gboolean); + return TRUE; + case G_TYPE_LONG: + if (tsize) *tsize = sizeof (glong); + return TRUE; + case G_TYPE_ULONG: + if (tsize) *tsize = sizeof (gulong); + return TRUE; + case G_TYPE_INT: + if (tsize) *tsize = sizeof (gint); + return TRUE; + case G_TYPE_UINT: + if (tsize) *tsize = sizeof (guint); + return TRUE; + case G_TYPE_INT64: + if (tsize) *tsize = sizeof (gint64); + return TRUE; + case G_TYPE_UINT64: + if (tsize) *tsize = sizeof (guint64); + return TRUE; + case G_TYPE_FLOAT: + if (tsize) *tsize = sizeof (gfloat); + return TRUE; + case G_TYPE_DOUBLE: + if (tsize) *tsize = sizeof (gdouble); + return TRUE; + default: + return FALSE; + } +} + +#define FLOAT_FACTOR 0.00000001 + +static gint +nm_gvalues_compare_fixed (const GValue *value1, const GValue *value2) +{ + int ret = 0; + + switch (G_VALUE_TYPE (value1)) { + case G_TYPE_CHAR: { + gchar val1 = g_value_get_char (value1); + gchar val2 = g_value_get_char (value2); + if (val1 != val2) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + case G_TYPE_UCHAR: { + guchar val1 = g_value_get_uchar (value1); + guchar val2 = g_value_get_uchar (value2); + if (val1 != val2) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + case G_TYPE_BOOLEAN: { + gboolean val1 = g_value_get_boolean (value1); + gboolean val2 = g_value_get_boolean (value2); + if (val1 != val2) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + case G_TYPE_LONG: { + glong val1 = g_value_get_long (value1); + glong val2 = g_value_get_long (value2); + if (val1 != val2) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + case G_TYPE_ULONG: { + gulong val1 = g_value_get_ulong (value1); + gulong val2 = g_value_get_ulong (value2); + if (val1 != val2) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + case G_TYPE_INT: { + gint val1 = g_value_get_int (value1); + gint val2 = g_value_get_int (value2); + if (val1 != val2) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + case G_TYPE_UINT: { + guint val1 = g_value_get_uint (value1); + guint val2 = g_value_get_uint (value2); + if (val1 != val2) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + case G_TYPE_INT64: { + gint64 val1 = g_value_get_int64 (value1); + gint64 val2 = g_value_get_int64 (value2); + if (val1 != val2) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + case G_TYPE_UINT64: { + guint64 val1 = g_value_get_uint64 (value1); + guint64 val2 = g_value_get_uint64 (value2); + if (val1 != val2) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + case G_TYPE_FLOAT: { + gfloat val1 = g_value_get_float (value1); + gfloat val2 = g_value_get_float (value2); + /* Can't use == or != here due to inexactness of FP */ + if (fabsf (val1 - val2) > FLOAT_FACTOR) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + case G_TYPE_DOUBLE: { + gdouble val1 = g_value_get_double (value1); + gdouble val2 = g_value_get_double (value2); + if (fabs (val1 - val2) > FLOAT_FACTOR) + ret = val1 < val2 ? -1 : val1 > val2; + break; + } + default: + g_warning ("Unhandled fixed size type '%s'", G_VALUE_TYPE_NAME (value1)); + } + + return ret; +} + +static gint +nm_gvalues_compare_string (const GValue *value1, const GValue *value2) +{ + const char *str1 = g_value_get_string (value1); + const char *str2 = g_value_get_string (value2); + + if (str1 == str2) + return 0; + + if (!str1) + return 1; + if (!str2) + return -1; + + return strcmp (str1, str2); +} + +static gint +nm_gvalues_compare_strv (const GValue *value1, const GValue *value2) +{ + char **strv1; + char **strv2; + gint ret; + guint i = 0; + + strv1 = (char **) g_value_get_boxed (value1); + strv2 = (char **) g_value_get_boxed (value2); + + while (strv1[i] && strv2[i]) { + ret = strcmp (strv1[i], strv2[i]); + if (ret) + return ret; + i++; + } + + if (strv1[i] == NULL && strv2[i] == NULL) + return 0; + + if (strv1[i]) + return 1; + + return -1; +} + +static void +nm_gvalue_destroy (gpointer data) +{ + GValue *value = (GValue *) data; + + g_value_unset (value); + g_slice_free (GValue, value); +} + +static GValue * +nm_gvalue_dup (const GValue *value) +{ + GValue *dup; + + dup = g_slice_new0 (GValue); + g_value_init (dup, G_VALUE_TYPE (value)); + g_value_copy (value, dup); + + return dup; +} + +static void +iterate_collection (const GValue *value, gpointer user_data) +{ + GSList **list = (GSList **) user_data; + + *list = g_slist_prepend (*list, nm_gvalue_dup (value)); +} + +static gint +nm_gvalues_compare_collection (const GValue *value1, const GValue *value2) +{ + gint ret; + guint len1; + guint len2; + GType value_type = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value1)); + gsize element_size = 0; + + if (type_is_fixed_size (value_type, &element_size)) { + gpointer data1 = NULL; + gpointer data2 = NULL; + + dbus_g_type_collection_get_fixed ((GValue *) value1, &data1, &len1); + dbus_g_type_collection_get_fixed ((GValue *) value2, &data2, &len2); + + if (len1 != len2) + ret = len1 < len2 ? -1 : len1 > len2; + else + ret = memcmp (data1, data2, len1 * element_size); + } else { + GSList *list1 = NULL; + GSList *list2 = NULL; + + dbus_g_type_collection_value_iterate (value1, iterate_collection, &list1); + len1 = g_slist_length (list1); + dbus_g_type_collection_value_iterate (value2, iterate_collection, &list2); + len2 = g_slist_length (list2); + + if (len1 != len2) + ret = len1 < len2 ? -1 : len1 > len2; + else { + GSList *iter1; + GSList *iter2; + + for (iter1 = list1, iter2 = list2, ret = 0; + ret == 0 && iter1 && iter2; + iter1 = iter1->next, iter2 = iter2->next) + ret = nm_gvalues_compare ((GValue *) iter1->data, (GValue *) iter2->data); + } + + g_slist_foreach (list1, (GFunc) nm_gvalue_destroy, NULL); + g_slist_free (list1); + g_slist_foreach (list2, (GFunc) nm_gvalue_destroy, NULL); + g_slist_free (list2); + } + + return ret; +} + +static void +iterate_map (const GValue *key_val, + const GValue *value_val, + gpointer user_data) +{ + GHashTable **hash = (GHashTable **) user_data; + + g_hash_table_insert (*hash, g_value_dup_string (key_val), nm_gvalue_dup (value_val)); +} + +typedef struct { + GHashTable *hash2; + gint ret; +} CompareMapInfo; + +static void +compare_one_map_item (gpointer key, gpointer val, gpointer user_data) +{ + CompareMapInfo *info = (CompareMapInfo *) user_data; + GValue *value2; + + if (info->ret) + return; + + value2 = (GValue *) g_hash_table_lookup (info->hash2, key); + if (value2) + info->ret = nm_gvalues_compare ((GValue *) val, value2); + else + info->ret = 1; +} + +static gint +nm_gvalues_compare_map (const GValue *value1, const GValue *value2) +{ + GHashTable *hash1 = NULL; + GHashTable *hash2 = NULL; + guint len1; + guint len2; + gint ret = 0; + + if (dbus_g_type_get_map_key_specialization (G_VALUE_TYPE (value1)) != G_TYPE_STRING) { + g_warning ("Can not compare maps with '%s' for keys", + g_type_name (dbus_g_type_get_map_key_specialization (G_VALUE_TYPE (value1)))); + return 0; + } + + hash1 = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nm_gvalue_destroy); + dbus_g_type_map_value_iterate (value1, iterate_map, &hash1); + len1 = g_hash_table_size (hash1); + + hash2 = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nm_gvalue_destroy); + dbus_g_type_map_value_iterate (value2, iterate_map, &hash2); + len2 = g_hash_table_size (hash2); + + if (len1 != len2) + ret = len1 < len2 ? -1 : len1 > len2; + else { + CompareMapInfo info; + + info.ret = 0; + info.hash2 = hash2; + g_hash_table_foreach (hash1, compare_one_map_item, &info); + ret = info.ret; + } + + g_hash_table_destroy (hash1); + g_hash_table_destroy (hash2); + + return ret; +} + +static gint +nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2) +{ + GValueArray *values1, *values2; + GValue *tmp_val; + GByteArray *addr1, *addr2; + guint32 prefix1, prefix2; + GByteArray *gw1, *gw2; + gint ret = 0; + int i; + + /* IP6 addresses are GValueArrays (see nm-dbus-glib-types.h) */ + values1 = g_value_get_boxed (value1); + values2 = g_value_get_boxed (value2); + + /* Since they are NM IPv6 address structures, we expect both + * to contain two elements as specified in nm-dbus-glib-types.h. + */ + g_return_val_if_fail (values1->n_values == 3, 0); + g_return_val_if_fail (values2->n_values == 3, 0); + + /* First struct IPv6 address */ + tmp_val = g_value_array_get_nth (values1, 0); + addr1 = g_value_get_boxed (tmp_val); + /* First struct IPv6 prefix */ + tmp_val = g_value_array_get_nth (values1, 1); + prefix1 = g_value_get_uint (tmp_val); + /* First struct IPv6 gateway */ + tmp_val = g_value_array_get_nth (values1, 2); + gw1 = g_value_get_boxed (tmp_val); + + /* Second struct IPv6 address */ + tmp_val = g_value_array_get_nth (values2, 0); + addr2 = g_value_get_boxed (tmp_val); + /* Second struct IPv6 prefix */ + tmp_val = g_value_array_get_nth (values2, 1); + prefix2 = g_value_get_uint (tmp_val); + /* Second struct IPv6 gateway */ + tmp_val = g_value_array_get_nth (values2, 2); + gw2 = g_value_get_boxed (tmp_val); + + /* Compare IPv6 addresses */ + if (prefix1 != prefix2) + return prefix1 < prefix2 ? -1 : prefix1 > prefix2; + + if (!IN6_ARE_ADDR_EQUAL ((struct in6_addr *)addr1->data, (struct in6_addr *)addr2->data)) { + for (i = 0; ret == 0 && i < addr1->len; i++) + ret = addr1->data[i] < addr2->data[i] ? -1 : addr1->data[i] > addr2->data[i]; + } + + if (!IN6_ARE_ADDR_EQUAL ((struct in6_addr *) gw1->data, (struct in6_addr *) gw2->data)) { + for (i = 0; ret == 0 && i < gw1->len; i++) + ret = gw1->data[i] < gw2->data[i] ? -1 : gw1->data[i] > gw2->data[i]; + } + + return ret; +} + +static gint +nm_gvalue_ip6_route_compare (const GValue *value1, const GValue *value2) +{ + GValueArray *values1, *values2; + GValue *tmp_val; + GByteArray *dest1, *dest2; + GByteArray *next_hop1, *next_hop2; + guint32 prefix1, prefix2; + guint32 metric1, metric2; + gint ret = 0; + int i; + + /* IP6 routes are GValueArrays (see nm-dbus-glib-types.h) */ + values1 = g_value_get_boxed (value1); + values2 = g_value_get_boxed (value2); + + /* Since they are NM IPv6 route structures, we expect both + * to contain 4 elements as specified in nm-dbus-glib-types.h. + */ + g_return_val_if_fail (values1->n_values == 4, 0); + g_return_val_if_fail (values2->n_values == 4, 0); + + /* First struct IPv6 route */ + tmp_val = g_value_array_get_nth (values1, 0); + dest1 = g_value_get_boxed (tmp_val); + tmp_val = g_value_array_get_nth (values1, 1); + prefix1 = g_value_get_uint (tmp_val); + tmp_val = g_value_array_get_nth (values1, 2); + next_hop1 = g_value_get_boxed (tmp_val); + tmp_val = g_value_array_get_nth (values1, 3); + metric1 = g_value_get_uint (tmp_val); + + /* Second struct IPv6 route */ + tmp_val = g_value_array_get_nth (values2, 0); + dest2 = g_value_get_boxed (tmp_val); + tmp_val = g_value_array_get_nth (values2, 1); + prefix2 = g_value_get_uint (tmp_val); + tmp_val = g_value_array_get_nth (values2, 2); + next_hop2 = g_value_get_boxed (tmp_val); + tmp_val = g_value_array_get_nth (values2, 3); + metric2 = g_value_get_uint (tmp_val); + + /* Compare the routes */ + if (prefix1 != prefix2) + return prefix1 < prefix2 ? -1 : prefix1 > prefix2; + + if (!IN6_ARE_ADDR_EQUAL ((struct in6_addr *)dest1->data, (struct in6_addr *)dest2->data)) { + for (i = 0; ret == 0 && i < dest1->len; i++) + ret = dest1->data[i] < dest2->data[i] ? -1 : dest1->data[i] > dest2->data[i]; + } + + if (!IN6_ARE_ADDR_EQUAL ((struct in6_addr *)next_hop1->data, (struct in6_addr *)next_hop2->data)) { + for (i = 0; ret == 0 && i < next_hop1->len; i++) + ret = next_hop1->data[i] < next_hop2->data[i] ? -1 : next_hop1->data[i] > next_hop2->data[i]; + } + + if (metric1 != metric2) + ret = metric1 < metric2 ? -1 : metric1 > metric2; + + return ret; +} + +static gint +nm_gvalues_compare_struct (const GValue *value1, const GValue *value2) +{ + /* value1 and value2 must contain the same type since + * nm_gvalues_compare() enforced that already. + */ + + if (G_VALUE_HOLDS (value1, DBUS_TYPE_G_IP6_ADDRESS)) { + return nm_gvalue_ip6_address_compare (value1, value2); + } else if (G_VALUE_HOLDS (value1, DBUS_TYPE_G_IP6_ROUTE)) { + return nm_gvalue_ip6_route_compare (value1, value2); + } else { + g_warning ("Don't know how to compare structures"); + return (value1 == value2); + } +} + +gint +nm_gvalues_compare (const GValue *value1, const GValue *value2) +{ + GType type1; + GType type2; + gint ret; + + if (value1 == value2) + return 0; + if (!value1) + return 1; + if (!value2) + return -1; + + type1 = G_VALUE_TYPE (value1); + type2 = G_VALUE_TYPE (value2); + + if (type1 != type2) + return type1 < type2 ? -1 : type1 > type2; + + if (type_is_fixed_size (type1, NULL)) + ret = nm_gvalues_compare_fixed (value1, value2); + else if (type1 == G_TYPE_STRING) + ret = nm_gvalues_compare_string (value1, value2); + else if (G_VALUE_HOLDS_BOXED (value1)) { + gpointer p1 = g_value_get_boxed (value1); + gpointer p2 = g_value_get_boxed (value2); + + if (p1 == p2) + ret = 0; /* Exactly the same values */ + else if (!p1) + ret = 1; /* The comparision functions below don't handle NULLs */ + else if (!p2) + ret = -1; /* The comparision functions below don't handle NULLs */ + else if (type1 == G_TYPE_STRV) + ret = nm_gvalues_compare_strv (value1, value2); + else if (dbus_g_type_is_collection (type1)) + ret = nm_gvalues_compare_collection (value1, value2); + else if (dbus_g_type_is_map (type1)) + ret = nm_gvalues_compare_map (value1, value2); + else if (dbus_g_type_is_struct (type1)) + ret = nm_gvalues_compare_struct (value1, value2); + else if (type1 == G_TYPE_VALUE) + ret = nm_gvalues_compare ((GValue *) g_value_get_boxed (value1), (GValue *) g_value_get_boxed (value2)); + else { + g_warning ("Don't know how to compare boxed types '%s'", g_type_name (type1)); + ret = value1 == value2; + } + } else { + g_warning ("Don't know how to compare types '%s'", g_type_name (type1)); + ret = value1 == value2; + } + + return ret; +} + +/***********************************************************/ + +static void +param_specialized_init (GParamSpec *pspec) +{ +} + +static void +param_specialized_set_default (GParamSpec *pspec, GValue *value) +{ + value->data[0].v_pointer = NULL; +} + +static gboolean +param_specialized_validate (GParamSpec *pspec, GValue *value) +{ + NMParamSpecSpecialized *sspec = NM_PARAM_SPEC_SPECIALIZED (pspec); + GType value_type = G_VALUE_TYPE (value); + gboolean changed = FALSE; + + if (!g_value_type_compatible (value_type, G_PARAM_SPEC_VALUE_TYPE (sspec))) { + g_value_reset (value); + changed = TRUE; + } + + return changed; +} + +static gint +param_specialized_values_cmp (GParamSpec *pspec, + const GValue *value1, + const GValue *value2) +{ + return nm_gvalues_compare (value1, value2); +} + +GType +_nm_param_spec_specialized_get_type (void) +{ + static GType type; + + if (G_UNLIKELY (type) == 0) { + static const GParamSpecTypeInfo pspec_info = { + sizeof (NMParamSpecSpecialized), + 0, + param_specialized_init, + G_TYPE_OBJECT, /* value_type */ + NULL, /* finalize */ + param_specialized_set_default, + param_specialized_validate, + param_specialized_values_cmp, + }; + type = g_param_type_register_static ("NMParamSpecSpecialized", &pspec_info); + } + + return type; +} + +GParamSpec * +_nm_param_spec_specialized (const char *name, + const char *nick, + const char *blurb, + GType specialized_type, + GParamFlags flags) +{ + NMParamSpecSpecialized *pspec; + + g_return_val_if_fail (g_type_is_a (specialized_type, G_TYPE_BOXED), NULL); + + pspec = g_param_spec_internal (NM_TYPE_PARAM_SPEC_SPECIALIZED, + name, nick, blurb, flags); + + G_PARAM_SPEC (pspec)->value_type = specialized_type; + + return G_PARAM_SPEC (pspec); +} + +/***********************************************************/ +/* Tests */ + +#if 0 + +static void +compare_ints (void) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + + g_value_init (&value1, G_TYPE_INT); + g_value_init (&value2, G_TYPE_INT); + + g_value_set_int (&value1, 5); + g_value_set_int (&value2, 5); + g_print ("Comparing ints 5 and 5: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_value_set_int (&value2, 10); + g_print ("Comparing ints 5 and 10: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_value_set_int (&value2, 1); + g_print ("Comparing ints 5 and 1: %d\n", nm_gvalues_compare (&value1, &value2)); +} + +static void +compare_strings (void) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + const char *str1 = "hello"; + const char *str2 = "world"; + + g_value_init (&value1, G_TYPE_STRING); + g_value_init (&value2, G_TYPE_STRING); + + g_value_set_string (&value1, str1); + g_value_set_string (&value2, str1); + g_print ("Comparing identical strings: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_value_set_string (&value2, str2); + g_print ("Comparing different strings: %d\n", nm_gvalues_compare (&value1, &value2)); +} + +static void +compare_strv (void) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + char *strv1[] = { "foo", "bar", "baz", NULL }; + char *strv2[] = { "foo", "bar", "bar", NULL }; + char *strv3[] = { "foo", "bar", NULL }; + char *strv4[] = { "foo", "bar", "baz", "bam", NULL }; + + g_value_init (&value1, G_TYPE_STRV); + g_value_init (&value2, G_TYPE_STRV); + + g_value_set_boxed (&value1, strv1); + g_value_set_boxed (&value2, strv1); + g_print ("Comparing identical strv's: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_value_set_boxed (&value2, strv2); + g_print ("Comparing different strv's: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_value_set_boxed (&value2, strv3); + g_print ("Comparing different len (smaller) strv's: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_value_set_boxed (&value2, strv4); + g_print ("Comparing different len (longer) strv's: %d\n", nm_gvalues_compare (&value1, &value2)); +} + +static void +compare_garrays (void) +{ + GArray *array1; + GArray *array2; + GValue value1 = { 0 }; + GValue value2 = { 0 }; + int i; + + g_value_init (&value1, DBUS_TYPE_G_UINT_ARRAY); + array1 = g_array_new (FALSE, FALSE, sizeof (guint32)); + + g_value_init (&value2, DBUS_TYPE_G_UINT_ARRAY); + array2 = g_array_new (FALSE, FALSE, sizeof (guint32)); + + for (i = 0; i < 5; i++) { + g_array_append_val (array1, i); + g_array_append_val (array2, i); + } + + g_value_set_boxed (&value1, array1); + g_value_set_boxed (&value2, array2); + + g_print ("Comparing identical arrays's: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_array_remove_index (array2, 0); + g_value_set_boxed (&value2, array2); + g_print ("Comparing different length arrays's: %d\n", nm_gvalues_compare (&value1, &value2)); + + i = 7; + g_array_prepend_val (array2, i); + g_value_set_boxed (&value2, array2); + g_print ("Comparing different arrays's: %d\n", nm_gvalues_compare (&value1, &value2)); +} + +static void +compare_ptrarrays (void) +{ + GPtrArray *array1; + GPtrArray *array2; + GValue value1 = { 0 }; + GValue value2 = { 0 }; + + g_value_init (&value1, dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING)); + array1 = g_ptr_array_new (); + + g_value_init (&value2, dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING)); + array2 = g_ptr_array_new (); + + g_ptr_array_add (array1, "hello"); + g_ptr_array_add (array1, "world"); + g_value_set_boxed (&value1, array1); + + g_ptr_array_add (array2, "hello"); + g_ptr_array_add (array2, "world"); + g_value_set_boxed (&value2, array2); + + g_print ("Comparing identical ptr arrays's: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_ptr_array_add (array2, "boo"); + g_value_set_boxed (&value2, array2); + g_print ("Comparing different len ptr arrays's: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_ptr_array_add (array1, "booz"); + g_value_set_boxed (&value1, array1); + g_print ("Comparing different ptr arrays's: %d\n", nm_gvalues_compare (&value1, &value2)); +} + +static void +compare_str_hash (void) +{ + GHashTable *hash1; + GHashTable *hash2; + GValue value1 = { 0 }; + GValue value2 = { 0 }; + + g_value_init (&value1, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING)); + g_value_init (&value2, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING)); + + hash1 = g_hash_table_new (g_str_hash, g_str_equal); + hash2 = g_hash_table_new (g_str_hash, g_str_equal); + + g_hash_table_insert (hash1, "key1", "hello"); + g_hash_table_insert (hash1, "key2", "world"); + + g_hash_table_insert (hash2, "key1", "hello"); + g_hash_table_insert (hash2, "key2", "world"); + + g_value_set_boxed (&value1, hash1); + g_value_set_boxed (&value2, hash2); + g_print ("Comparing identical str hashes: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_hash_table_remove (hash2, "key2"); + g_value_set_boxed (&value2, hash2); + g_print ("Comparing different length str hashes: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_hash_table_insert (hash2, "key2", "moon"); + g_value_set_boxed (&value2, hash2); + g_print ("Comparing different str hashes: %d\n", nm_gvalues_compare (&value1, &value2)); +} + +static GValue * +str_to_gvalue (const char *str) +{ + GValue *value; + + value = g_slice_new0 (GValue); + g_value_init (value, G_TYPE_STRING); + g_value_set_string (value, str); + + return value; +} + +static GValue * +int_to_gvalue (int i) +{ + GValue *value; + + value = g_slice_new0 (GValue); + g_value_init (value, G_TYPE_INT); + g_value_set_int (value, i); + + return value; +} + +static void +compare_gvalue_hash (void) +{ + GHashTable *hash1; + GHashTable *hash2; + GValue value1 = { 0 }; + GValue value2 = { 0 }; + + g_value_init (&value1, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)); + g_value_init (&value2, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)); + + hash1 = g_hash_table_new (g_str_hash, g_str_equal); + hash2 = g_hash_table_new (g_str_hash, g_str_equal); + + g_hash_table_insert (hash1, "key1", str_to_gvalue ("hello")); + g_hash_table_insert (hash1, "key2", int_to_gvalue (5)); + + g_hash_table_insert (hash2, "key1", str_to_gvalue ("hello")); + g_hash_table_insert (hash2, "key2", int_to_gvalue (5)); + + g_value_set_boxed (&value1, hash1); + g_value_set_boxed (&value2, hash2); + g_print ("Comparing identical gvalue hashes: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_hash_table_remove (hash2, "key2"); + g_value_set_boxed (&value2, hash2); + g_print ("Comparing different length str hashes: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_hash_table_insert (hash2, "key2", str_to_gvalue ("moon")); + g_value_set_boxed (&value2, hash2); + g_print ("Comparing different str hashes: %d\n", nm_gvalues_compare (&value1, &value2)); +} + +static void +compare_ip6_addresses (void) +{ + GValueArray *array1; + GValueArray *array2; + GValueArray *array3; + GByteArray *ba1; + GByteArray *ba2; + GByteArray *ba3; + GValue element = { 0 }; + GValue value1 = { 0 }; + GValue value2 = { 0 }; + struct in6_addr addr1; + struct in6_addr addr2; + struct in6_addr addr3; + guint32 prefix1 = 64; + guint32 prefix2 = 64; + guint32 prefix3 = 0; + + inet_pton (AF_INET6, "1:2:3:4:5:6:7:8", &addr1, sizeof (struct in6_addr)); + inet_pton (AF_INET6, "ffff:2:3:4:5:6:7:8", &addr2, sizeof (struct in6_addr)); + inet_pton (AF_INET6, "::", &addr3, sizeof (struct in6_addr)); + + /* address 1 */ + ba1 = g_byte_array_new (); + array1 = g_value_array_new (2); + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + g_byte_array_append (ba1, (guint8 *) addr1.s6_addr, 16); + g_value_take_boxed (&element, ba1); + g_value_array_append (array1, &element); + g_value_unset (&element); + + g_value_init (&element, G_TYPE_UINT); + g_value_set_uint (&element, prefix1); + g_value_array_append (array1, &element); + g_value_unset (&element); + + /* address 2 */ + ba2 = g_byte_array_new (); + array2 = g_value_array_new (2); + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + g_byte_array_append (ba2, (guint8 *) addr2.s6_addr, 16); + g_value_take_boxed (&element, ba2); + g_value_array_append (array2, &element); + g_value_unset (&element); + + g_value_init (&element, G_TYPE_UINT); + g_value_set_uint (&element, prefix2); + g_value_array_append (array2, &element); + g_value_unset (&element); + + /* address 3 */ + ba3 = g_byte_array_new (); + array3 = g_value_array_new (2); + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + g_byte_array_append (ba3, (guint8 *) addr3.s6_addr, 16); + g_value_take_boxed (&element, ba3); + g_value_array_append (array3, &element); + g_value_unset (&element); + + g_value_init (&element, G_TYPE_UINT); + g_value_set_uint (&element, prefix3); + g_value_array_append (array3, &element); + g_value_unset (&element); + + g_value_init (&value1, DBUS_TYPE_G_IP6_ADDRESS); + g_value_init (&value2, DBUS_TYPE_G_IP6_ADDRESS); + + g_value_set_boxed (&value1, array1); + g_value_set_boxed (&value2, array1); + g_print ("Comparing identical IPv6 address structures: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_value_set_boxed (&value1, array1); + g_value_set_boxed (&value2, array2); + g_print ("Comparing different IPv6 address structures: %d\n", nm_gvalues_compare (&value1, &value2)); + + g_value_set_boxed (&value1, array1); + g_value_set_boxed (&value2, array3); + g_print ("Comparing different IPv6 address structures: %d\n", nm_gvalues_compare (&value1, &value2)); +} + +int +main (int argc, char *argv[]) +{ + DBusGConnection *bus; + + g_type_init (); + bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + + compare_ints (); + compare_strings (); + compare_strv (); + compare_garrays (); + compare_ptrarrays (); + compare_str_hash (); + compare_gvalue_hash (); + compare_ip6_addresses (); + + return 0; +} + +#endif diff --git a/libnm-util/nm-param-spec-specialized.h b/libnm-util/nm-param-spec-specialized.h new file mode 100644 index 00000000..a6173674 --- /dev/null +++ b/libnm-util/nm-param-spec-specialized.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_PARAM_SPEC_SPECIALIZED_H +#define NM_PARAM_SPEC_SPECIALIZED_H + +#include <glib-object.h> + +typedef struct _NMParamSpecSpecialized NMParamSpecSpecialized; + +#define NM_TYPE_PARAM_SPEC_SPECIALIZED (_nm_param_spec_specialized_get_type ()) + +#define NM_IS_PARAM_SPEC_SPECIALIZED(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), NM_TYPE_PARAM_SPEC_SPECIALIZED)) +#define NM_PARAM_SPEC_SPECIALIZED(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), NM_TYPE_PARAM_SPEC_SPECIALIZED, NMParamSpecSpecialized)) + +GType _nm_param_spec_specialized_get_type (void); + +GParamSpec *_nm_param_spec_specialized (const char *name, + const char *nick, + const char *blurb, + GType specialized_type, + GParamFlags flags); + +#endif /* NM_PARAM_SPEC_SPECIALIZED_H */ diff --git a/libnm-util/nm-setting-8021x.c b/libnm-util/nm-setting-8021x.c new file mode 100644 index 00000000..eea6ba5e --- /dev/null +++ b/libnm-util/nm-setting-8021x.c @@ -0,0 +1,3440 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> +#include <ctype.h> +#include <dbus/dbus-glib.h> +#include "nm-setting-8021x.h" +#include "nm-param-spec-specialized.h" +#include "nm-utils.h" +#include "nm-dbus-glib-types.h" +#include "crypto.h" +#include "nm-utils-private.h" + +/** + * SECTION:nm-setting-8021x + * @short_description: Describes 802.1x-authenticated connection properties + * @include: nm-setting-8021x.h + * + * The #NMSetting8021x object is a #NMSetting subclass that describes + * properties necessary for connection to 802.1x-authenticated networks, such as + * WPA and WPA2 Enterprise WiFi networks and wired 802.1x networks. 802.1x + * connections typically use certificates and/or EAP authentication methods to + * securely verify, identify, and authenticate the client to the network itself, + * instead of simply relying on a widely shared static key. + * + * It's a good idea to read up on wpa_supplicant configuration before using this + * setting extensively, since most of the options here correspond closely with + * the relevant wpa_supplicant configuration options. + * + * Furthermore, to get a good idea of 802.1x, EAP, TLS, TTLS, etc and their + * applications to WiFi and wired networks, you'll want to get copies of the + * following books. + * + * 802.11 Wireless Networks: The Definitive Guide, Second Edition + * Author: Matthew Gast + * ISBN: 978-0596100520 + * + * Cisco Wireless LAN Security + * Authors: Krishna Sankar, Sri Sundaralingam, Darrin Miller, and Andrew Balinsky + * ISBN: 978-1587051548 + **/ + +#define SCHEME_PATH "file://" + +/** + * nm_setting_802_1x_error_quark: + * + * Registers an error quark for #NMSetting8021x if necessary. + * + * Returns: the error quark used for #NMSetting8021x errors. + **/ +GQuark +nm_setting_802_1x_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-802-1x-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_802_1x_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_802_1X_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, "MissingProperty"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSetting8021xError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING) + +#define NM_SETTING_802_1X_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate)) + +typedef struct { + GSList *eap; /* GSList of strings */ + char *identity; + char *anonymous_identity; + GByteArray *ca_cert; + char *ca_path; + GByteArray *client_cert; + char *phase1_peapver; + char *phase1_peaplabel; + char *phase1_fast_provisioning; + char *phase2_auth; + char *phase2_autheap; + GByteArray *phase2_ca_cert; + char *phase2_ca_path; + GByteArray *phase2_client_cert; + char *password; + char *pin; + char *psk; + GByteArray *private_key; + char *private_key_password; + GByteArray *phase2_private_key; + char *phase2_private_key_password; + gboolean system_ca_certs; +} NMSetting8021xPrivate; + +enum { + PROP_0, + PROP_EAP, + PROP_IDENTITY, + PROP_ANONYMOUS_IDENTITY, + PROP_CA_CERT, + PROP_CA_PATH, + PROP_CLIENT_CERT, + PROP_PHASE1_PEAPVER, + PROP_PHASE1_PEAPLABEL, + PROP_PHASE1_FAST_PROVISIONING, + PROP_PHASE2_AUTH, + PROP_PHASE2_AUTHEAP, + PROP_PHASE2_CA_CERT, + PROP_PHASE2_CA_PATH, + PROP_PHASE2_CLIENT_CERT, + PROP_PASSWORD, + PROP_PRIVATE_KEY, + PROP_PRIVATE_KEY_PASSWORD, + PROP_PHASE2_PRIVATE_KEY, + PROP_PHASE2_PRIVATE_KEY_PASSWORD, + PROP_PIN, + PROP_PSK, + PROP_SYSTEM_CA_CERTS, + + LAST_PROP +}; + +/** + * nm_setting_802_1x_new: + * + * Creates a new #NMSetting8021x object with default values. + * + * Returns: the new empty #NMSetting8021x object + **/ +NMSetting * +nm_setting_802_1x_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_802_1X, NULL); +} + +/** + * nm_setting_802_1x_get_num_eap_methods: + * @setting: the #NMSetting8021x + * + * Returns the number of eap methods allowed for use when connecting to the + * network. Generally only one EAP method is used. Use the functions + * nm_setting_802_1x_get_eap_method(), nm_setting_802_1x_add_eap_method(), + * and nm_setting_802_1x_remove_eap_method() for adding, removing, and retrieving + * allowed EAP methods. + * + * Returns: the number of allowed EAP methods + **/ +guint32 +nm_setting_802_1x_get_num_eap_methods (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0); + + return g_slist_length (NM_SETTING_802_1X_GET_PRIVATE (setting)->eap); +} + +/** + * nm_setting_802_1x_get_eap_method: + * @setting: the #NMSetting8021x + * @i: the index of the EAP method name to return + * + * Returns the name of the allowed EAP method at index @i. + * + * Returns: the name of the allowed EAP method at index @i + **/ +const char * +nm_setting_802_1x_get_eap_method (NMSetting8021x *setting, guint32 i) +{ + NMSetting8021xPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + priv = NM_SETTING_802_1X_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->eap), NULL); + + return (const char *) g_slist_nth_data (priv->eap, i); +} + +/** + * nm_setting_802_1x_add_eap_method: + * @setting: the #NMSetting8021x + * @eap: the name of the EAP method to allow for this connection + * + * Adds an allowed EAP method. The setting is not valid until at least one + * EAP method has been added. See #NMSetting8021x:eap property for a list of + * allowed EAP methods. + * + * Returns: TRUE if the EAP method was successfully added, FALSE if it was + * not a valid method or if it was already allowed. + **/ +gboolean +nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap) +{ + NMSetting8021xPrivate *priv; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); + g_return_val_if_fail (eap != NULL, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE (setting); + for (iter = priv->eap; iter; iter = g_slist_next (iter)) { + if (!strcmp (eap, (char *) iter->data)) + return FALSE; + } + + priv->eap = g_slist_append (priv->eap, g_ascii_strdown (eap, -1)); + return TRUE; +} + +/** + * nm_setting_802_1x_remove_eap_method: + * @setting: the #NMSetting8021x + * @i: the index of the EAP method to remove + * + * Removes the allowed EAP method at the specified index. + **/ +void +nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i) +{ + NMSetting8021xPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_802_1X (setting)); + + priv = NM_SETTING_802_1X_GET_PRIVATE (setting); + elt = g_slist_nth (priv->eap, i); + g_return_if_fail (elt != NULL); + + g_free (elt->data); + priv->eap = g_slist_delete_link (priv->eap, elt); +} + +/** + * nm_setting_802_1x_clear_eap_methods: + * @setting: the #NMSetting8021x + * + * Clears all allowed EAP methods. + **/ +void +nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting) +{ + NMSetting8021xPrivate *priv; + + g_return_if_fail (NM_IS_SETTING_802_1X (setting)); + + priv = NM_SETTING_802_1X_GET_PRIVATE (setting); + nm_utils_slist_free (priv->eap, g_free); + priv->eap = NULL; +} + +/** + * nm_setting_802_1x_get_identity: + * @setting: the #NMSetting8021x + * + * Returns the identifier used by some EAP methods (like TLS) to + * authenticate the user. Often this is a username or login name. + * + * Returns: the user identifier + **/ +const char * +nm_setting_802_1x_get_identity (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->identity; +} + +/** + * nm_setting_802_1x_get_anonymous_identity: + * @setting: the #NMSetting8021x + * + * Returns the anonymous identifier used by some EAP methods (like TTLS) to + * authenticate the user in the outer unencrypted "phase 1" authentication. The + * inner "phase 2" authentication will use the #NMSetting8021x:identity in + * a secure form, if applicable for that EAP method. + * + * Returns: the anonymous identifier + **/ +const char * +nm_setting_802_1x_get_anonymous_identity (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->anonymous_identity; +} + +/** + * nm_setting_802_1x_get_ca_path: + * @setting: the #NMSetting8021x + * + * Returns the path of the CA certificate directory if previously set. Systems + * will often have a directory that contains multiple individual CA certificates + * which the supplicant can then add to the verification chain. This may be + * used in addition to the #NMSetting8021x:ca-cert property to add more CA + * certificates for verifying the network to client. + * + * Returns: the CA certificate directory path + **/ +const char * +nm_setting_802_1x_get_ca_path (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_path; +} + +/** + * nm_setting_802_1x_get_system_ca_certs: + * @setting: the #NMSetting8021x + * + * Sets the #NMSetting8021x:system-ca-certs property. The + * #NMSetting8021x:ca-path and #NMSetting8021x:phase2-ca-path + * properties are ignored if the #NMSetting8021x:system-ca-certs property is + * TRUE, in which case a system-wide CA certificate directory specified at + * compile time (using the --system-ca-path configure option) is used in place + * of these properties. + * + * Returns: TRUE if a system CA certificate path should be used, FALSE if not + **/ +gboolean +nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->system_ca_certs; +} + +static NMSetting8021xCKScheme +get_cert_scheme (GByteArray *array) +{ + if (!array || !array->len) + return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN; + + if ( (array->len > strlen (SCHEME_PATH)) + && !memcmp (array->data, SCHEME_PATH, strlen (SCHEME_PATH))) + return NM_SETTING_802_1X_CK_SCHEME_PATH; + + return NM_SETTING_802_1X_CK_SCHEME_BLOB; +} + +/** + * nm_setting_802_1x_get_ca_cert_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the CA certificate. If the returned scheme + * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_ca_cert_blob(); + * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_ca_cert_path(). + * + * Returns: scheme used to store the CA certificate (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); + + return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert); +} + +/** + * nm_setting_802_1x_get_ca_cert_blob: + * @setting: the #NMSetting8021x + * + * Returns the CA certificate blob if the CA certificate is stored using the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use a + * CA certificate (LEAP for example), and those that can take advantage of the + * CA certificate allow it to be unset. Note that lack of a CA certificate + * reduces security by allowing man-in-the-middle attacks, because the identity + * of the network cannot be confirmed by the client. + * + * Returns: the CA certificate data + **/ +const GByteArray * +nm_setting_802_1x_get_ca_cert_blob (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_ca_cert_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert; +} + +/** + * nm_setting_802_1x_get_ca_cert: + * @setting: the #NMSetting8021x + * + * Returns the CA certificate blob if the CA certificate is stored using the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use a + * CA certificate (LEAP for example), and those that can take advantage of the + * CA certificate allow it to be unset. Note that lack of a CA certificate + * reduces security by allowing man-in-the-middle attacks, because the identity + * of the network cannot be confirmed by the client. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_get_ca_cert_blob(). + * + * Returns: the CA certificate data + **/ +const GByteArray * +nm_setting_802_1x_get_ca_cert (NMSetting8021x *setting) +{ + return nm_setting_802_1x_get_ca_cert_blob (setting); +} + +/** + * nm_setting_802_1x_get_ca_cert_path: + * @setting: the #NMSetting8021x + * + * Returns the CA certificate path if the CA certificate is stored using the + * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. Not all EAP methods use a + * CA certificate (LEAP for example), and those that can take advantage of the + * CA certificate allow it to be unset. Note that lack of a CA certificate + * reduces security by allowing man-in-the-middle attacks, because the identity + * of the network cannot be confirmed by the client. + * + * Returns: path to the CA certificate file + **/ +const char * +nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_ca_cert_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); + + return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert->data + strlen (SCHEME_PATH)); +} + +/** + * nm_setting_802_1x_set_ca_cert: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or + * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the CA certificate file + * (PEM or DER format). The path must be UTF-8 encoded; use + * g_filename_to_utf8() to convert if needed. Passing NULL with any @scheme + * clears the CA certificate. + * @scheme: desired storage scheme for the certificate + * @out_format: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:ca-cert property + * with the raw certificate data if using the %NM_SETTING_802_1X_CK_SCHEME_BLOB + * scheme, or with the path to the certificate file if using the + * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_ca_cert (NMSetting8021x *self, + const char *value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error) +{ + NMSetting8021xPrivate *priv; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + GByteArray *data; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); + + if (value) { + g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); + g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB + || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, + FALSE); + } + + if (out_format) + g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + /* Clear out any previous ca_cert blob */ + if (priv->ca_cert) { + g_byte_array_free (priv->ca_cert, TRUE); + priv->ca_cert = NULL; + } + + if (!value) + return TRUE; + + data = crypto_load_and_verify_certificate (value, &format, error); + if (data) { + /* wpa_supplicant can only use raw x509 CA certs */ + switch (format) { + case NM_CRYPTO_FILE_FORMAT_X509: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_X509; + break; + default: + g_byte_array_free (data, TRUE); + data = NULL; + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_CA_CERT); + break; + } + + if (data) { + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) + priv->ca_cert = data; + else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + /* Add the path scheme tag to the front, then the fielname */ + priv->ca_cert = g_byte_array_sized_new (strlen (value) + strlen (SCHEME_PATH) + 1); + g_byte_array_append (priv->ca_cert, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH)); + g_byte_array_append (priv->ca_cert, (const guint8 *) value, strlen (value)); + g_byte_array_append (priv->ca_cert, (const guint8 *) "\0", 1); + } else + g_assert_not_reached (); + } + } + + return priv->ca_cert != NULL; +} + +static NMSetting8021xCKType +ck_format_to_type (NMSetting8021xCKFormat format) +{ + switch (format) { + case NM_SETTING_802_1X_CK_FORMAT_X509: + return NM_SETTING_802_1X_CK_TYPE_X509; + case NM_SETTING_802_1X_CK_FORMAT_RAW_KEY: + return NM_SETTING_802_1X_CK_TYPE_RAW_KEY; + case NM_SETTING_802_1X_CK_FORMAT_PKCS12: + return NM_SETTING_802_1X_CK_TYPE_PKCS12; + default: + break; + } + return NM_SETTING_802_1X_CK_TYPE_UNKNOWN; +} + +/** + * nm_setting_802_1x_set_ca_cert_from_file: + * @setting: the #NMSetting8021x + * @filename: the path of the CA certificate file (PEM or DER format). Passing + * NULL clears the CA certificate. + * @out_ck_type: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:ca-cert property + * with the raw certificate data using the %NM_SETTING_802_1X_CK_SCHEME_BLOB + * scheme. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_set_ca_cert() with the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_ca_cert_from_file (NMSetting8021x *setting, + const char *filename, + NMSetting8021xCKType *out_ck_type, + GError **error) +{ + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + + success = nm_setting_802_1x_set_ca_cert (setting, + filename, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + error); + if (success && out_ck_type) + *out_ck_type = ck_format_to_type (format); + + return success; +} + +/** + * nm_setting_802_1x_get_client_cert_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the client certificate. If the returned scheme + * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_client_cert_blob(); + * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_client_cert_path(). + * + * Returns: scheme used to store the client certificate (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); + + return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert); +} + +/** + * nm_setting_802_1x_get_client_cert_blob: + * @setting: the #NMSetting8021x + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: the client certificate data + **/ +const GByteArray * +nm_setting_802_1x_get_client_cert_blob (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_client_cert_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert; +} + +/** + * nm_setting_802_1x_get_client_cert: + * @setting: the #NMSetting8021x + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_get_client_cert_blob(). + * + * Returns: the client certificate data + **/ +const GByteArray * +nm_setting_802_1x_get_client_cert (NMSetting8021x *setting) +{ + return nm_setting_802_1x_get_client_cert_blob (setting); +} + +/** + * nm_setting_802_1x_get_client_cert_path: + * @setting: the #NMSetting8021x + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: path to the client certificate file + **/ +const char * +nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_client_cert_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); + + return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert->data + strlen (SCHEME_PATH)); +} + +/** + * nm_setting_802_1x_set_client_cert: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or + * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the client certificate + * file (PEM, DER, or PKCS#12 format). The path must be UTF-8 encoded; use + * g_filename_to_utf8() to convert if needed. Passing NULL with any @scheme + * clears the client certificate. + * @scheme: desired storage scheme for the certificate + * @out_format: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:client-cert + * property with the raw certificate data if using the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate + * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_client_cert (NMSetting8021x *self, + const char *value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error) +{ + NMSetting8021xPrivate *priv; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + GByteArray *data; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); + + if (value) { + g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); + g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB + || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, + FALSE); + } + + if (out_format) + g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + /* Clear out any previous ca_cert blob */ + if (priv->client_cert) { + g_byte_array_free (priv->client_cert, TRUE); + priv->client_cert = NULL; + } + + if (!value) + return TRUE; + + data = crypto_load_and_verify_certificate (value, &format, error); + if (data) { + /* wpa_supplicant can only use raw x509 CA certs */ + switch (format) { + case NM_CRYPTO_FILE_FORMAT_X509: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_X509; + break; + case NM_CRYPTO_FILE_FORMAT_PKCS12: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12; + break; + default: + g_byte_array_free (data, TRUE); + data = NULL; + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_CLIENT_CERT); + break; + } + + if (data) { + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) + priv->client_cert = data; + else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + /* Add the path scheme tag to the front, then the fielname */ + priv->client_cert = g_byte_array_sized_new (strlen (value) + strlen (SCHEME_PATH) + 1); + g_byte_array_append (priv->client_cert, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH)); + g_byte_array_append (priv->client_cert, (const guint8 *) value, strlen (value)); + g_byte_array_append (priv->client_cert, (const guint8 *) "\0", 1); + } else + g_assert_not_reached (); + } + } + + return priv->client_cert != NULL; +} + +/** + * nm_setting_802_1x_set_client_cert_from_file: + * @setting: the #NMSetting8021x + * @filename: the path of the client certificate file (PEM, DER, or + * PKCS#12 format). Passing NULL clears the client certificate. + * @out_ck_type: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:client-cert + * property with the raw certificate data. + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_set_client_cert() with the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_client_cert_from_file (NMSetting8021x *setting, + const char *filename, + NMSetting8021xCKType *out_ck_type, + GError **error) +{ + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + + success = nm_setting_802_1x_set_client_cert (setting, + filename, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + error); + if (success && out_ck_type) + *out_ck_type = ck_format_to_type (format); + + return success; +} + +/** + * nm_setting_802_1x_get_phase1_peapver: + * @setting: the #NMSetting8021x + * + * Returns: the "phase 1" PEAP version to be used when authenticating with + * EAP-PEAP as contained in the #NMSetting8021x:phase1-peapver property. Valid + * values are NULL (unset), "0" (PEAP version 0), and "1" (PEAP version 1). + **/ +const char * +nm_setting_802_1x_get_phase1_peapver (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_peapver; +} + +/** + * nm_setting_802_1x_get_phase1_peaplabel: + * @setting: the #NMSetting8021x + * + * Returns: whether the "phase 1" PEAP label is new-style or old-style, to be + * used when authenticating with EAP-PEAP, as contained in the + * #NMSetting8021x:phase1-peaplabel property. Valid values are NULL (unset), + * "0" (use old-style label), and "1" (use new-style label). See the + * wpa_supplicant documentation for more details. + **/ +const char * +nm_setting_802_1x_get_phase1_peaplabel (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_peaplabel; +} + +/** + * nm_setting_802_1x_get_phase1_fast_provisioning: + * @setting: the #NMSetting8021x + * + * Returns: whether "phase 1" PEAP fast provisioning should be used, as specified + * by the #NMSetting8021x:phase1-fast-provisioning property. See the + * wpa_supplicant documentation for more details. + **/ +const char * +nm_setting_802_1x_get_phase1_fast_provisioning (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_fast_provisioning; +} + +/** + * nm_setting_802_1x_get_phase2_auth: + * @setting: the #NMSetting8021x + * + * Returns: the "phase 2" non-EAP (ex MD5) allowed authentication method as + * specified by the #NMSetting8021x:phase2-auth property. + **/ +const char * +nm_setting_802_1x_get_phase2_auth (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_auth; +} + +/** + * nm_setting_802_1x_get_phase2_autheap: + * @setting: the #NMSetting8021x + * + * Returns: the "phase 2" EAP-based (ex TLS) allowed authentication method as + * specified by the #NMSetting8021x:phase2-autheap property. + **/ +const char * +nm_setting_802_1x_get_phase2_autheap (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_autheap; +} + +/** + * nm_setting_802_1x_get_phase2_ca_path: + * @setting: the #NMSetting8021x + * + * Returns the path of the "phase 2" CA certificate directory if previously set. + * Systems will often have a directory that contains multiple individual CA + * certificates which the supplicant can then add to the verification chain. + * This may be used in addition to the #NMSetting8021x:phase2-ca-cert property + * to add more CA certificates for verifying the network to client. + * + * Returns: the "phase 2" CA certificate directory path + **/ +const char * +nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_path; +} + +/** + * nm_setting_802_1x_get_phase2_ca_cert_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the "phase 2" CA certificate. If the + * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use + * nm_setting_802_1x_get_ca_cert_blob(); if %NM_SETTING_802_1X_CK_SCHEME_PATH, + * use nm_setting_802_1x_get_ca_cert_path(). + * + * Returns: scheme used to store the "phase 2" CA certificate (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_phase2_ca_cert_scheme (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); + + return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert); +} + +/** + * nm_setting_802_1x_get_phase2_ca_cert_blob: + * @setting: the #NMSetting8021x + * + * Returns the "phase 2" CA certificate blob if the CA certificate is stored + * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use + * a CA certificate (LEAP for example), and those that can take advantage of the + * CA certificate allow it to be unset. Note that lack of a CA certificate + * reduces security by allowing man-in-the-middle attacks, because the identity + * of the network cannot be confirmed by the client. + * + * Returns: the "phase 2" CA certificate data + **/ +const GByteArray * +nm_setting_802_1x_get_phase2_ca_cert_blob (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert; +} + +/** + * nm_setting_802_1x_get_phase2_ca_cert: + * @setting: the #NMSetting8021x + * + * Returns the "phase 2" CA certificate blob. Not all EAP methods use + * a CA certificate (LEAP for example), and those that can take advantage of the + * CA certificate allow it to be unset. Note that lack of a CA certificate + * reduces security by allowing man-in-the-middle attacks, because the identity + * of the network cannot be confirmed by the client. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_get_phase2_ca_cert_blob(). + * + * Returns: the "phase 2" CA certificate data + **/ +const GByteArray * +nm_setting_802_1x_get_phase2_ca_cert (NMSetting8021x *setting) +{ + return nm_setting_802_1x_get_phase2_ca_cert_blob (setting); +} + +/** + * nm_setting_802_1x_get_phase2_ca_cert_path: + * @setting: the #NMSetting8021x + * + * Returns the "phase 2" CA certificate path if the CA certificate is stored + * using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. Not all EAP methods use + * a CA certificate (LEAP for example), and those that can take advantage of the + * CA certificate allow it to be unset. Note that lack of a CA certificate + * reduces security by allowing man-in-the-middle attacks, because the identity + * of the network cannot be confirmed by the client. + * + * Returns: path to the "phase 2" CA certificate file + **/ +const char * +nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); + + return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert->data + strlen (SCHEME_PATH)); +} + +/** + * nm_setting_802_1x_set_phase2_ca_cert: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or + * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" CA + * certificate file (PEM or DER format). The path must be UTF-8 encoded; use + * g_filename_to_utf8() to convert if needed. Passing NULL with any @scheme + * clears the "phase2" CA certificate. + * @scheme: desired storage scheme for the certificate + * @out_format: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:phase2-ca-cert + * property with the raw certificate data if using the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate + * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *self, + const char *value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error) +{ + NMSetting8021xPrivate *priv; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + GByteArray *data; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); + + if (value) { + g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); + g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB + || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, + FALSE); + } + + if (out_format) + g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + /* Clear out any previous ca_cert blob */ + if (priv->phase2_ca_cert) { + g_byte_array_free (priv->phase2_ca_cert, TRUE); + priv->phase2_ca_cert = NULL; + } + + if (!value) + return TRUE; + + data = crypto_load_and_verify_certificate (value, &format, error); + if (data) { + /* wpa_supplicant can only use raw x509 CA certs */ + switch (format) { + case NM_CRYPTO_FILE_FORMAT_X509: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_X509; + break; + default: + g_byte_array_free (data, TRUE); + data = NULL; + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE2_CA_CERT); + break; + } + + if (data) { + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) + priv->phase2_ca_cert = data; + else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + /* Add the path scheme tag to the front, then the fielname */ + priv->phase2_ca_cert = g_byte_array_sized_new (strlen (value) + strlen (SCHEME_PATH) + 1); + g_byte_array_append (priv->phase2_ca_cert, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH)); + g_byte_array_append (priv->phase2_ca_cert, (const guint8 *) value, strlen (value)); + g_byte_array_append (priv->phase2_ca_cert, (const guint8 *) "\0", 1); + } else + g_assert_not_reached (); + } + } + + return priv->phase2_ca_cert != NULL; +} + +/** + * nm_setting_802_1x_set_phase2_ca_cert_from_file: + * @setting: the #NMSetting8021x + * @filename: the path of the "phase2" CA certificate file (PEM or DER format). + * Passing NULL with any @scheme clears the "phase2" CA certificate. + * @out_ck_type: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:phase2-ca-cert + * property with the raw certificate data. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_set_phase2_ca_cert(). + * with the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_phase2_ca_cert_from_file (NMSetting8021x *setting, + const char *filename, + NMSetting8021xCKType *out_ck_type, + GError **error) +{ + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + + success = nm_setting_802_1x_set_phase2_ca_cert (setting, + filename, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + error); + if (success && out_ck_type) + *out_ck_type = ck_format_to_type (format); + + return success; +} + +/** + * nm_setting_802_1x_get_phase2_client_cert_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the "phase 2" client certificate. If the + * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use + * nm_setting_802_1x_get_client_cert_blob(); if + * %NM_SETTING_802_1X_CK_SCHEME_PATH, use + * nm_setting_802_1x_get_client_cert_path(). + * + * Returns: scheme used to store the "phase 2" client certificate (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); + + return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert); +} + +/** + * nm_setting_802_1x_get_phase2_client_cert_blob: + * @setting: the #NMSetting8021x + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: the "phase 2" client certificate data + **/ +const GByteArray * +nm_setting_802_1x_get_phase2_client_cert_blob (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert; +} + +/** + * nm_setting_802_1x_get_phase2_client_cert: + * @setting: the #NMSetting8021x + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_get_phase2_client_cert_blob(). + * + * Returns: the "phase 2" client certificate data + **/ +const GByteArray * +nm_setting_802_1x_get_phase2_client_cert (NMSetting8021x *setting) +{ + return nm_setting_802_1x_get_phase2_client_cert_blob (setting); +} + +/** + * nm_setting_802_1x_get_phase2_client_cert_path: + * @setting: the #NMSetting8021x + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: path to the "phase 2" client certificate file + **/ +const char * +nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); + + return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert->data + strlen (SCHEME_PATH)); +} + +/** + * nm_setting_802_1x_set_phase2_client_cert: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or + * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" client + * certificate file (PEM, DER, or PKCS#12 format). The path must be UTF-8 + * encoded; use g_filename_to_utf8() to convert if needed. Passing NULL with + * any @scheme clears the "phase2" client certificate. + * @scheme: desired storage scheme for the certificate + * @out_format: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:phase2-client-cert + * property with the raw certificate data if using the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate + * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *self, + const char *value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error) +{ + NMSetting8021xPrivate *priv; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + GByteArray *data; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); + + if (value) { + g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); + g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB + || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, + FALSE); + } + + if (out_format) + g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + /* Clear out any previous ca_cert blob */ + if (priv->phase2_client_cert) { + g_byte_array_free (priv->phase2_client_cert, TRUE); + priv->phase2_client_cert = NULL; + } + + if (!value) + return TRUE; + + data = crypto_load_and_verify_certificate (value, &format, error); + if (data) { + /* wpa_supplicant can only use raw x509 CA certs */ + switch (format) { + case NM_CRYPTO_FILE_FORMAT_X509: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_X509; + break; + case NM_CRYPTO_FILE_FORMAT_PKCS12: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12; + break; + default: + g_byte_array_free (data, TRUE); + data = NULL; + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + break; + } + + if (data) { + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) + priv->phase2_client_cert = data; + else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + /* Add the path scheme tag to the front, then the fielname */ + priv->phase2_client_cert = g_byte_array_sized_new (strlen (value) + strlen (SCHEME_PATH) + 1); + g_byte_array_append (priv->phase2_client_cert, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH)); + g_byte_array_append (priv->phase2_client_cert, (const guint8 *) value, strlen (value)); + g_byte_array_append (priv->phase2_client_cert, (const guint8 *) "\0", 1); + } else + g_assert_not_reached (); + } + } + + return priv->phase2_client_cert != NULL; +} + +/** + * nm_setting_802_1x_set_phase2_client_cert_from_file: + * @setting: the #NMSetting8021x + * @filename: pass the path of the "phase2" client certificate file (PEM, DER, + * or PKCS#12 format). Passing NULL clears the "phase2" client certificate. + * @out_ck_type: on successful return, the type of the certificate added + * @error: on unsuccessful return, an error + * + * Reads a certificate from disk and sets the #NMSetting8021x:phase2-client-cert + * property with the raw certificate data. + * + * Client certificates are used to identify the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_set_phase2_client_cert() with the. + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_phase2_client_cert_from_file (NMSetting8021x *setting, + const char *filename, + NMSetting8021xCKType *out_ck_type, + GError **error) +{ + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + + success = nm_setting_802_1x_set_phase2_client_cert (setting, + filename, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + error); + if (success && out_ck_type) + *out_ck_type = ck_format_to_type (format); + + return success; +} + +/** + * nm_setting_802_1x_get_password: + * @setting: the #NMSetting8021x + * + * Returns: the password used by the authentication method, if any, as specified + * by the #NMSetting8021x:password property + **/ +const char * +nm_setting_802_1x_get_password (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->password; +} + +/** + * nm_setting_802_1x_get_pin: + * @setting: the #NMSetting8021x + * + * Returns: the PIN used by the authentication method, if any, as specified + * by the #NMSetting8021x:pin property + **/ +const char * +nm_setting_802_1x_get_pin (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->pin; +} + +/** + * nm_setting_802_1x_get_psk: + * @setting: the #NMSetting8021x + * + * Returns: the Pre-Shared-Key used by the authentication method, if any, as + * specified by the #NMSetting8021x:psk property + **/ +const char * +nm_setting_802_1x_get_psk (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->psk; +} + +/** + * nm_setting_802_1x_get_private_key_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the private key. If the returned scheme is + * %NM_SETTING_802_1X_CK_SCHEME_BLOB, use + * nm_setting_802_1x_get_client_cert_blob(); if + * %NM_SETTING_802_1X_CK_SCHEME_PATH, use + * nm_setting_802_1x_get_client_cert_path(). + * + * Returns: scheme used to store the private key (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_private_key_scheme (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); + + return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key); +} + +/** + * nm_setting_802_1x_get_private_key_blob: + * @setting: the #NMSetting8021x + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: the private key data + **/ +const GByteArray * +nm_setting_802_1x_get_private_key_blob (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_private_key_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key; +} + +/** + * nm_setting_802_1x_get_private_key: + * @setting: the #NMSetting8021x + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_get_private_key_blob(). + * + * Returns: the private key data + **/ +const GByteArray * +nm_setting_802_1x_get_private_key (NMSetting8021x *setting) +{ + return nm_setting_802_1x_get_private_key_blob (setting); +} + +/** + * nm_setting_802_1x_get_private_key_path: + * @setting: the #NMSetting8021x + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: path to the private key file + **/ +const char * +nm_setting_802_1x_get_private_key_path (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_private_key_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); + + return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key->data + strlen (SCHEME_PATH)); +} + +/** + * nm_setting_802_1x_set_private_key: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or + * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the private key file + * (PEM, DER, or PKCS#12 format). The path must be UTF-8 encoded; use + * g_filename_to_utf8() to convert if needed. Passing NULL with any @scheme + * clears the private key. + * @password: password used to decrypt the private key + * @scheme: desired storage scheme for the private key + * @out_format: on successful return, the type of the private key added + * @error: on unsuccessful return, an error + * + * Reads a private key from disk and sets the #NMSetting8021x:private-key + * property with the raw private key data if using the + * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the private key + * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_private_key (NMSetting8021x *self, + const char *value, + const char *password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error) +{ + NMSetting8021xPrivate *priv; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + GByteArray *data; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); + + if (value) { + g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); + g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB + || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, + FALSE); + } + + if (out_format) + g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + /* Clear out any previous private key blob */ + if (priv->private_key) { + /* Try not to leave the private key around in memory */ + memset (priv->private_key, 0, priv->private_key->len); + g_byte_array_free (priv->private_key, TRUE); + priv->private_key = NULL; + } + + g_free (priv->private_key_password); + priv->private_key_password = NULL; + + if (!value) + return TRUE; + + /* Verify the key and the private key password */ + data = crypto_get_private_key (value, + password, + &key_type, + &format, + error); + if (!data) { + /* As a special case for private keys, even if the decrypt fails, + * return the key's file type. + */ + if (out_format && crypto_is_pkcs12_file (value, NULL)) + *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12; + + return FALSE; + } + + switch (format) { + case NM_CRYPTO_FILE_FORMAT_RAW_KEY: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; + break; + case NM_CRYPTO_FILE_FORMAT_X509: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_X509; + break; + case NM_CRYPTO_FILE_FORMAT_PKCS12: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12; + break; + default: + memset (data->data, 0, data->len); + g_byte_array_free (data, TRUE); + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PRIVATE_KEY); + return FALSE; + } + + g_assert (data); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + priv->private_key = data; + data = NULL; + + /* Always update the private key for blob + pkcs12 since the + * pkcs12 files are encrypted + */ + if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) + priv->private_key_password = g_strdup (password); + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + /* Add the path scheme tag to the front, then the fielname */ + priv->private_key = g_byte_array_sized_new (strlen (value) + strlen (SCHEME_PATH) + 1); + g_byte_array_append (priv->private_key, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH)); + g_byte_array_append (priv->private_key, (const guint8 *) value, strlen (value)); + g_byte_array_append (priv->private_key, (const guint8 *) "\0", 1); + + /* Always update the private key with paths since the key the + * cert refers to is encrypted. + */ + priv->private_key_password = g_strdup (password); + } else + g_assert_not_reached (); + + /* Clear and free private key data if it's no longer needed */ + if (data) { + memset (data->data, 0, data->len); + g_byte_array_free (data, TRUE); + } + + /* As required by NM and wpa_supplicant, set the client-cert + * property to the same PKCS#12 data. + */ + if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) { + if (priv->client_cert) + g_byte_array_free (priv->client_cert, TRUE); + + priv->client_cert = g_byte_array_sized_new (priv->private_key->len); + g_byte_array_append (priv->client_cert, priv->private_key->data, priv->private_key->len); + } + + return priv->private_key != NULL; +} + +/** + * nm_setting_802_1x_set_private_key_from_file: + * @setting: the #NMSetting8021x + * @filename: the path of the private key file (PEM, DER, or PKCS#12 format). + * Passing NULL clears the private key. + * @password: password used to decrypt the private key + * @out_ck_type: on successful return, the type of the private key added + * @error: on unsuccessful return, an error + * + * Reads a private key from disk and sets the #NMSetting8021x:private-key + * property with the raw private key data. + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_set_private_key() with. + * the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_private_key_from_file (NMSetting8021x *setting, + const char *filename, + const char *password, + NMSetting8021xCKType *out_ck_type, + GError **error) +{ + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + + success = nm_setting_802_1x_set_private_key (setting, + filename, + password, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + error); + if (success && out_ck_type) + *out_ck_type = ck_format_to_type (format); + + return success; +} + +/** + * nm_setting_802_1x_get_private_key_password: + * @setting: the #NMSetting8021x + * + * Returns: the private key password used to decrypt the private key if + * previously set with nm_setting_802_1x_set_private_key_from_file(), + * nm_setting_802_1x_set_private_key_path(), or the + * #NMSetting8021x:private-key-password property. + **/ +const char * +nm_setting_802_1x_get_private_key_password (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key_password; +} + +/** + * nm_setting_802_1x_get_private_key_format: + * @setting: the #NMSetting8021x + * + * Returns: the data format of the private key data stored in the + * #NMSetting8021x:private-key property + **/ +NMSetting8021xCKFormat +nm_setting_802_1x_get_private_key_format (NMSetting8021x *setting) +{ + NMSetting8021xPrivate *priv; + const char *path; + GError *error = NULL; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + priv = NM_SETTING_802_1X_GET_PRIVATE (setting); + + if (!priv->private_key) + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + + switch (nm_setting_802_1x_get_private_key_scheme (setting)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + if (crypto_is_pkcs12_data (priv->private_key)) + return NM_SETTING_802_1X_CK_FORMAT_PKCS12; + return NM_SETTING_802_1X_CK_FORMAT_X509; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + path = nm_setting_802_1x_get_private_key_path (setting); + if (crypto_is_pkcs12_file (path, &error)) + return NM_SETTING_802_1X_CK_FORMAT_PKCS12; + if (error) { + /* Couldn't read the file or something */ + g_error_free (error); + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + } + return NM_SETTING_802_1X_CK_FORMAT_X509; + default: + break; + } + + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; +} + +/** + * nm_setting_802_1x_get_private_key_type: + * @setting: the #NMSetting8021x + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_get_private_key_format(). + * + * Returns: the data format of the private key data stored in the + * #NMSetting8021x:private-key property + **/ +NMSetting8021xCKType +nm_setting_802_1x_get_private_key_type (NMSetting8021x *setting) +{ + return ck_format_to_type (nm_setting_802_1x_get_private_key_format (setting)); +} + +/** + * nm_setting_802_1x_get_phase2_private_key_password: + * @setting: the #NMSetting8021x + * + * Returns: the private key password used to decrypt the private key if + * previously set with nm_setting_802_1x_set_phase2_private_key_from_file(), + * nm_setting_802_1x_set_phase2_private_key_path(), or the + * #NMSetting8021x:phase2-private-key-password property. + **/ +const char * +nm_setting_802_1x_get_phase2_private_key_password (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key_password; +} + +/** + * nm_setting_802_1x_get_phase2_private_key_scheme: + * @setting: the #NMSetting8021x + * + * Returns the scheme used to store the "phase 2" private key. If the returned + * scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use + * nm_setting_802_1x_get_client_cert_blob(); if + * %NM_SETTING_802_1X_CK_SCHEME_PATH, use + * nm_setting_802_1x_get_client_cert_path(). + * + * Returns: scheme used to store the "phase 2" private key (blob or path) + **/ +NMSetting8021xCKScheme +nm_setting_802_1x_get_phase2_private_key_scheme (NMSetting8021x *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); + + return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key); +} + +/** + * nm_setting_802_1x_get_phase2_private_key_blob: + * @setting: the #NMSetting8021x + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: the "phase 2" private key data + **/ +const GByteArray * +nm_setting_802_1x_get_phase2_private_key_blob (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); + + return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key; +} + +/** + * nm_setting_802_1x_get_phase2_private_key: + * @setting: the #NMSetting8021x + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_get_private_key_blob(). + * + * Returns: the "phase 2" private key data + **/ +const GByteArray * +nm_setting_802_1x_get_phase2_private_key (NMSetting8021x *setting) +{ + return nm_setting_802_1x_get_phase2_private_key_blob (setting); +} + +/** + * nm_setting_802_1x_get_phase2_private_key_path: + * @setting: the #NMSetting8021x + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: path to the "phase 2" private key file + **/ +const char * +nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting) +{ + NMSetting8021xCKScheme scheme; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL); + + scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting); + g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); + + return (const char *) (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key->data + strlen (SCHEME_PATH)); +} + +/** + * nm_setting_802_1x_set_phase2_private_key: + * @setting: the #NMSetting8021x + * @value: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or + * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" private + * key file (PEM, DER, or PKCS#12 format). The path must be UTF-8 encoded; + * use g_filename_to_utf8() to convert if needed. Passing NULL with any + * @scheme clears the "phase2" private key. + * @password: password used to decrypt the private key + * @scheme: desired storage scheme for the private key + * @out_format: on successful return, the type of the private key added + * @error: on unsuccessful return, an error + * + * Reads a "phase 2" private key from disk and sets the + * #NMSetting8021x:phase2-private-key property with the raw private key data if + * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the + * private key file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *self, + const char *value, + const char *password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error) +{ + NMSetting8021xPrivate *priv; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + GByteArray *data; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE); + + if (value) { + g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE); + g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB + || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, + FALSE); + } + + if (out_format) + g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE); + + priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + /* Clear out any previous private key blob */ + if (priv->phase2_private_key) { + /* Try not to leave the private key around in memory */ + memset (priv->phase2_private_key, 0, priv->phase2_private_key->len); + g_byte_array_free (priv->phase2_private_key, TRUE); + priv->phase2_private_key = NULL; + } + + g_free (priv->phase2_private_key_password); + priv->phase2_private_key_password = NULL; + + if (!value) + return TRUE; + + /* Verify the key and the private key password */ + data = crypto_get_private_key (value, + password, + &key_type, + &format, + error); + if (!data) { + /* As a special case for private keys, even if the decrypt fails, + * return the key's file type. + */ + if (out_format && crypto_is_pkcs12_file (value, NULL)) + *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12; + + return FALSE; + } + + switch (format) { + case NM_CRYPTO_FILE_FORMAT_RAW_KEY: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_RAW_KEY; + break; + case NM_CRYPTO_FILE_FORMAT_X509: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_X509; + break; + case NM_CRYPTO_FILE_FORMAT_PKCS12: + if (out_format) + *out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12; + break; + default: + memset (data->data, 0, data->len); + g_byte_array_free (data, TRUE); + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); + return FALSE; + } + + g_assert (data); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + priv->phase2_private_key = data; + data = NULL; + + /* Always update the private key for blob + pkcs12 since the + * pkcs12 files are encrypted + */ + if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) + priv->phase2_private_key_password = g_strdup (password); + } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + /* Add the path scheme tag to the front, then the fielname */ + priv->phase2_private_key = g_byte_array_sized_new (strlen (value) + strlen (SCHEME_PATH) + 1); + g_byte_array_append (priv->phase2_private_key, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH)); + g_byte_array_append (priv->phase2_private_key, (const guint8 *) value, strlen (value)); + g_byte_array_append (priv->phase2_private_key, (const guint8 *) "\0", 1); + + /* Always update the private key with paths since the key the + * cert refers to is encrypted. + */ + priv->phase2_private_key_password = g_strdup (password); + } else + g_assert_not_reached (); + + /* Clear and free private key data if it's no longer needed */ + if (data) { + memset (data->data, 0, data->len); + g_byte_array_free (data, TRUE); + } + + /* As required by NM and wpa_supplicant, set the client-cert + * property to the same PKCS#12 data. + */ + if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) { + if (priv->phase2_client_cert) + g_byte_array_free (priv->phase2_client_cert, TRUE); + + priv->phase2_client_cert = g_byte_array_sized_new (priv->phase2_private_key->len); + g_byte_array_append (priv->phase2_client_cert, priv->phase2_private_key->data, priv->phase2_private_key->len); + } + + return priv->phase2_private_key != NULL; +} + +/** + * nm_setting_802_1x_set_phase2_private_key_from_file: + * @setting: the #NMSetting8021x + * @filename: the path of the "phase2" private key file (PEM, DER, or PKCS#12 + * format). Passing NULL clears the "phase2" private key. + * @password: password used to decrypt the private key + * @out_ck_type: on successful return, the type of the private key added + * @error: on unsuccessful return, an error + * + * Reads a "phase 2" private key from disk and sets the + * #NMSetting8021x:phase2-private-key property with the raw private key data. + * + * Private keys are used to authenticate the connecting client to the network + * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x + * authentication method. + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_set_phase2_private_key() with + * the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. + * + * Returns: TRUE if the operation succeeded, FALSE if it was unsuccessful + **/ +gboolean +nm_setting_802_1x_set_phase2_private_key_from_file (NMSetting8021x *setting, + const char *filename, + const char *password, + NMSetting8021xCKType *out_ck_type, + GError **error) +{ + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + + success = nm_setting_802_1x_set_phase2_private_key (setting, + filename, + password, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + &format, + error); + if (success && out_ck_type) + *out_ck_type = ck_format_to_type (format); + + return success; +} + +/** + * nm_setting_802_1x_get_phase2_private_key_format: + * @setting: the #NMSetting8021x + * + * Returns: the data format of the "phase 2" private key data stored in the + * #NMSetting8021x:phase2-private-key property + **/ +NMSetting8021xCKFormat +nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting) +{ + NMSetting8021xPrivate *priv; + const char *path; + GError *error = NULL; + + g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); + priv = NM_SETTING_802_1X_GET_PRIVATE (setting); + + if (!priv->phase2_private_key) + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + + switch (nm_setting_802_1x_get_phase2_private_key_scheme (setting)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + if (crypto_is_pkcs12_data (priv->phase2_private_key)) + return NM_SETTING_802_1X_CK_FORMAT_PKCS12; + return NM_SETTING_802_1X_CK_FORMAT_X509; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + path = nm_setting_802_1x_get_phase2_private_key_path (setting); + if (crypto_is_pkcs12_file (path, &error)) + return NM_SETTING_802_1X_CK_FORMAT_PKCS12; + if (error) { + /* Couldn't read the file or something */ + g_error_free (error); + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + } + return NM_SETTING_802_1X_CK_FORMAT_X509; + default: + break; + } + + return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; +} + +/** + * nm_setting_802_1x_get_phase2_private_key_type: + * @setting: the #NMSetting8021x + * + * Deprecated: 0.8: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling nm_setting_802_1x_get_phase2_private_key_format(). + * + * Returns: the data format of the private key data stored in the + * #NMSetting8021x:phase2-private-key property + **/ +NMSetting8021xCKType +nm_setting_802_1x_get_phase2_private_key_type (NMSetting8021x *setting) +{ + return ck_format_to_type (nm_setting_802_1x_get_phase2_private_key_format (setting)); +} + +static void +need_secrets_password (NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + if (!priv->password || !strlen (priv->password)) + g_ptr_array_add (secrets, NM_SETTING_802_1X_PASSWORD); +} + +static void +need_secrets_sim (NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + if (!priv->pin || !strlen (priv->pin)) + g_ptr_array_add (secrets, NM_SETTING_802_1X_PIN); +} + +static gboolean +need_private_key_password (const GByteArray *blob, + const char *path, + const char *password) +{ + /* Private key password is only un-needed if the private key scheme is BLOB, + * because BLOB keys are decrypted by the settings service. A private key + * password is required if the private key is PKCS#12 format, or if the + * private key scheme is PATH. + */ + if (path) { + GByteArray *tmp; + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + NMCryptoFileFormat key_format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + + /* check the password */ + tmp = crypto_get_private_key (path, password, &key_type, &key_format, NULL); + if (tmp) { + /* Decrypt/verify successful; password must be OK */ + g_byte_array_free (tmp, TRUE); + return FALSE; + } + } else if (blob) { + /* Non-PKCS#12 blob-scheme keys are already decrypted by their settings + * service, thus if the private key is not PKCS#12 format, a new password + * is not required. If the PKCS#12 key can be decrypted with the given + * password, then we don't need a new password either. + */ + if (!crypto_is_pkcs12_data (blob) || crypto_verify_pkcs12 (blob, password, NULL)) + return FALSE; + } else + g_warning ("%s: unknown private key password scheme", __func__); + + return TRUE; +} + +static void +need_secrets_tls (NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + NMSetting8021xCKScheme scheme; + const GByteArray *blob = NULL; + const char *path = NULL; + + if (phase2) { + if (!priv->phase2_private_key || !priv->phase2_private_key->len) { + g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); + return; + } + + scheme = nm_setting_802_1x_get_phase2_private_key_scheme (self); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) + path = nm_setting_802_1x_get_phase2_private_key_path (self); + else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) + blob = nm_setting_802_1x_get_phase2_private_key_blob (self); + else { + g_warning ("%s: unknown phase2 private key scheme %d", __func__, scheme); + g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY); + return; + } + + if (need_private_key_password (blob, path, priv->phase2_private_key_password)) + g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); + } else { + if (!priv->private_key || !priv->private_key->len) { + g_ptr_array_add (secrets, NM_SETTING_802_1X_PRIVATE_KEY); + return; + } + + scheme = nm_setting_802_1x_get_private_key_scheme (self); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) + path = nm_setting_802_1x_get_private_key_path (self); + else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) + blob = nm_setting_802_1x_get_private_key_blob (self); + else { + g_warning ("%s: unknown private key scheme %d", __func__, scheme); + g_ptr_array_add (secrets, NM_SETTING_802_1X_PRIVATE_KEY); + return; + } + + if (need_private_key_password (blob, path, priv->private_key_password)) + g_ptr_array_add (secrets, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); + } +} + +static gboolean +verify_tls (NMSetting8021x *self, gboolean phase2, GError **error) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + if (phase2) { + if (!priv->phase2_client_cert) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + return FALSE; + } else if (!priv->phase2_client_cert->len) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + return FALSE; + } + + /* If the private key is PKCS#12, check that it matches the client cert */ + if (priv->phase2_private_key && crypto_is_pkcs12_data (priv->phase2_private_key)) { + if (priv->phase2_private_key->len != priv->phase2_client_cert->len) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + return FALSE; + } + + if (memcmp (priv->phase2_private_key->data, + priv->phase2_client_cert->data, + priv->phase2_private_key->len)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE2_CLIENT_CERT); + return FALSE; + } + } + } else { + if (!priv->client_cert) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, + NM_SETTING_802_1X_CLIENT_CERT); + return FALSE; + } else if (!priv->client_cert->len) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_CLIENT_CERT); + return FALSE; + } + + /* If the private key is PKCS#12, check that it matches the client cert */ + if (priv->private_key && crypto_is_pkcs12_data (priv->private_key)) { + if (priv->private_key->len != priv->client_cert->len) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_CLIENT_CERT); + return FALSE; + } + + if (memcmp (priv->private_key->data, + priv->client_cert->data, + priv->private_key->len)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_CLIENT_CERT); + return FALSE; + } + } + } + + return TRUE; +} + +static gboolean +verify_ttls (NMSetting8021x *self, gboolean phase2, GError **error) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + if ( (!priv->identity || !strlen (priv->identity)) + && (!priv->anonymous_identity || !strlen (priv->anonymous_identity))) { + if (!priv->identity) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, + NM_SETTING_802_1X_IDENTITY); + } else if (!strlen (priv->identity)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_IDENTITY); + } else if (!priv->anonymous_identity) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, + NM_SETTING_802_1X_ANONYMOUS_IDENTITY); + } else { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_ANONYMOUS_IDENTITY); + } + return FALSE; + } + + if ( (!priv->phase2_auth || !strlen (priv->phase2_auth)) + && (!priv->phase2_autheap || !strlen (priv->phase2_autheap))) { + if (!priv->phase2_auth) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, + NM_SETTING_802_1X_PHASE2_AUTH); + } else if (!strlen (priv->phase2_auth)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE2_AUTH); + } else if (!priv->phase2_autheap) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, + NM_SETTING_802_1X_PHASE2_AUTHEAP); + } else { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE2_AUTHEAP); + } + return FALSE; + } + + return TRUE; +} + +static gboolean +verify_identity (NMSetting8021x *self, gboolean phase2, GError **error) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + if (!priv->identity) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, + NM_SETTING_802_1X_IDENTITY); + } else if (!strlen (priv->identity)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_IDENTITY); + } + + return TRUE; +} + +/* Implemented below... */ +static void need_secrets_phase2 (NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2); + + +typedef void (*EAPMethodNeedSecretsFunc) (NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2); + +typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self, + gboolean phase2, + GError **error); + +typedef struct { + const char *method; + EAPMethodNeedSecretsFunc ns_func; + EAPMethodValidateFunc v_func; +} EAPMethodsTable; + +static EAPMethodsTable eap_methods_table[] = { + { "leap", need_secrets_password, verify_identity }, + { "md5", need_secrets_password, verify_identity }, + { "pap", need_secrets_password, verify_identity }, + { "chap", need_secrets_password, verify_identity }, + { "mschap", need_secrets_password, verify_identity }, + { "mschapv2", need_secrets_password, verify_identity }, + { "fast", need_secrets_password, verify_identity }, + { "tls", need_secrets_tls, verify_tls }, + { "peap", need_secrets_phase2, verify_ttls }, + { "ttls", need_secrets_phase2, verify_ttls }, + { "sim", need_secrets_sim, NULL }, + { "gtc", need_secrets_password, verify_identity }, + { "otp", NULL, NULL }, // FIXME: implement + { NULL, NULL, NULL } +}; + +static void +need_secrets_phase2 (NMSetting8021x *self, + GPtrArray *secrets, + gboolean phase2) +{ + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + char *method = NULL; + int i; + + g_return_if_fail (phase2 == FALSE); + + /* Check phase2_auth and phase2_autheap */ + method = priv->phase2_auth; + if (!method && priv->phase2_autheap) + method = priv->phase2_autheap; + + if (!method) { + g_warning ("Couldn't find EAP method."); + g_assert_not_reached(); + return; + } + + /* Ask the configured phase2 method if it needs secrets */ + for (i = 0; eap_methods_table[i].method; i++) { + if (eap_methods_table[i].ns_func == NULL) + continue; + if (!strcmp (eap_methods_table[i].method, method)) { + (*eap_methods_table[i].ns_func) (self, secrets, TRUE); + break; + } + } +} + + +static GPtrArray * +need_secrets (NMSetting *setting) +{ + NMSetting8021x *self = NM_SETTING_802_1X (setting); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + GSList *iter; + GPtrArray *secrets; + gboolean eap_method_found = FALSE; + + secrets = g_ptr_array_sized_new (4); + + /* Ask each configured EAP method if it needs secrets */ + for (iter = priv->eap; iter && !eap_method_found; iter = g_slist_next (iter)) { + const char *method = (const char *) iter->data; + int i; + + for (i = 0; eap_methods_table[i].method; i++) { + if (eap_methods_table[i].ns_func == NULL) + continue; + if (!strcmp (eap_methods_table[i].method, method)) { + (*eap_methods_table[i].ns_func) (self, secrets, FALSE); + + /* Only break out of the outer loop if this EAP method + * needed secrets. + */ + if (secrets->len > 0) + eap_method_found = TRUE; + break; + } + } + } + + if (secrets->len == 0) { + g_ptr_array_free (secrets, TRUE); + secrets = NULL; + } + + return secrets; +} + +static gboolean +verify_cert (GByteArray *array, const char *prop_name, GError **error) +{ + if (!array) + return TRUE; + + switch (get_cert_scheme (array)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + return TRUE; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + /* For path-based schemes, verify that the path is zero-terminated */ + if (array->data[array->len - 1] == '\0') { + /* And ensure it's UTF-8 valid too so we can pass it through + * D-Bus and stuff like that. + */ + if (g_utf8_validate ((const char *) (array->data + strlen (SCHEME_PATH)), -1, NULL)) + return TRUE; + } + break; + default: + break; + } + + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + "%s", prop_name); + return FALSE; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSetting8021x *self = NM_SETTING_802_1X (setting); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", NULL }; + const char *valid_phase1_peapver[] = { "0", "1", NULL }; + const char *valid_phase1_peaplabel[] = { "0", "1", NULL }; + const char *valid_phase1_fast_pac[] = { "0", "1", "2", "3", NULL }; + const char *valid_phase2_auth[] = { "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", "tls", NULL }; + const char *valid_phase2_autheap[] = { "md5", "mschapv2", "otp", "gtc", "tls", NULL }; + GSList *iter; + + if (error) + g_return_val_if_fail (*error == NULL, FALSE); + + if (!priv->eap) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, + NM_SETTING_802_1X_EAP); + return FALSE; + } + + if (!_nm_utils_string_slist_validate (priv->eap, valid_eap)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_EAP); + return FALSE; + } + + /* Ask each configured EAP method if its valid */ + for (iter = priv->eap; iter; iter = g_slist_next (iter)) { + const char *method = (const char *) iter->data; + int i; + + for (i = 0; eap_methods_table[i].method; i++) { + if (eap_methods_table[i].v_func == NULL) + continue; + if (!strcmp (eap_methods_table[i].method, method)) { + if (!(*eap_methods_table[i].v_func) (self, FALSE, error)) + return FALSE; + break; + } + } + } + + if (priv->phase1_peapver && !_nm_utils_string_in_list (priv->phase1_peapver, valid_phase1_peapver)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE1_PEAPVER); + return FALSE; + } + + if (priv->phase1_peaplabel && !_nm_utils_string_in_list (priv->phase1_peaplabel, valid_phase1_peaplabel)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE1_PEAPLABEL); + return FALSE; + } + + if (priv->phase1_fast_provisioning && !_nm_utils_string_in_list (priv->phase1_fast_provisioning, valid_phase1_fast_pac)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING); + return FALSE; + } + + if (priv->phase2_auth && !_nm_utils_string_in_list (priv->phase2_auth, valid_phase2_auth)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE2_AUTH); + return FALSE; + } + + if (priv->phase2_autheap && !_nm_utils_string_in_list (priv->phase2_autheap, valid_phase2_autheap)) { + g_set_error (error, + NM_SETTING_802_1X_ERROR, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_PHASE2_AUTHEAP); + return FALSE; + } + + if (!verify_cert (priv->ca_cert, NM_SETTING_802_1X_CA_CERT, error)) + return FALSE; + if (!verify_cert (priv->phase2_ca_cert, NM_SETTING_802_1X_PHASE2_CA_CERT, error)) + return FALSE; + + if (!verify_cert (priv->client_cert, NM_SETTING_802_1X_CLIENT_CERT, error)) + return FALSE; + if (!verify_cert (priv->phase2_client_cert, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, error)) + return FALSE; + + if (!verify_cert (priv->private_key, NM_SETTING_802_1X_PRIVATE_KEY, error)) + return FALSE; + if (!verify_cert (priv->phase2_private_key, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, error)) + return FALSE; + + /* FIXME: finish */ + + return TRUE; +} + +static void +nm_setting_802_1x_init (NMSetting8021x *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_802_1X_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSetting8021x *self = NM_SETTING_802_1X (object); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self); + + /* Strings first. g_free() already checks for NULLs so we don't have to */ + + g_free (priv->identity); + g_free (priv->anonymous_identity); + g_free (priv->ca_path); + g_free (priv->phase1_peapver); + g_free (priv->phase1_peaplabel); + g_free (priv->phase1_fast_provisioning); + g_free (priv->phase2_auth); + g_free (priv->phase2_autheap); + g_free (priv->phase2_ca_path); + g_free (priv->password); + + nm_utils_slist_free (priv->eap, g_free); + + if (priv->ca_cert) + g_byte_array_free (priv->ca_cert, TRUE); + if (priv->client_cert) + g_byte_array_free (priv->client_cert, TRUE); + if (priv->private_key) + g_byte_array_free (priv->private_key, TRUE); + g_free (priv->private_key_password); + if (priv->phase2_ca_cert) + g_byte_array_free (priv->phase2_ca_cert, TRUE); + if (priv->phase2_client_cert) + g_byte_array_free (priv->phase2_client_cert, TRUE); + if (priv->phase2_private_key) + g_byte_array_free (priv->phase2_private_key, TRUE); + g_free (priv->phase2_private_key_password); + + G_OBJECT_CLASS (nm_setting_802_1x_parent_class)->finalize (object); +} + +static GByteArray * +set_cert_prop_helper (const GValue *value, const char *prop_name, GError **error) +{ + gboolean valid; + GByteArray *data = NULL; + + data = g_value_dup_boxed (value); + /* Verify the new data */ + if (data) { + valid = verify_cert (data, prop_name, error); + if (!valid) { + g_byte_array_free (data, TRUE); + data = NULL; + } + } + return data; +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSetting8021x *setting = NM_SETTING_802_1X (object); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (setting); + GError *error = NULL; + + switch (prop_id) { + case PROP_EAP: + nm_utils_slist_free (priv->eap, g_free); + priv->eap = g_value_dup_boxed (value); + break; + case PROP_IDENTITY: + g_free (priv->identity); + priv->identity = g_value_dup_string (value); + break; + case PROP_ANONYMOUS_IDENTITY: + g_free (priv->anonymous_identity); + priv->anonymous_identity = g_value_dup_string (value); + break; + case PROP_CA_CERT: + if (priv->ca_cert) { + g_byte_array_free (priv->ca_cert, TRUE); + priv->ca_cert = NULL; + } + priv->ca_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_CA_CERT, &error); + if (error) { + g_warning ("Error setting certificate (invalid data): (%d) %s", + error->code, error->message); + g_error_free (error); + } + break; + case PROP_CA_PATH: + g_free (priv->ca_path); + priv->ca_path = g_value_dup_string (value); + break; + case PROP_CLIENT_CERT: + if (priv->client_cert) { + g_byte_array_free (priv->client_cert, TRUE); + priv->client_cert = NULL; + } + priv->client_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_CLIENT_CERT, &error); + if (error) { + g_warning ("Error setting certificate (invalid data): (%d) %s", + error->code, error->message); + g_error_free (error); + } + break; + case PROP_PHASE1_PEAPVER: + g_free (priv->phase1_peapver); + priv->phase1_peapver = g_value_dup_string (value); + break; + case PROP_PHASE1_PEAPLABEL: + g_free (priv->phase1_peaplabel); + priv->phase1_peaplabel = g_value_dup_string (value); + break; + case PROP_PHASE1_FAST_PROVISIONING: + g_free (priv->phase1_fast_provisioning); + priv->phase1_fast_provisioning = g_value_dup_string (value); + break; + case PROP_PHASE2_AUTH: + g_free (priv->phase2_auth); + priv->phase2_auth = g_value_dup_string (value); + break; + case PROP_PHASE2_AUTHEAP: + g_free (priv->phase2_autheap); + priv->phase2_autheap = g_value_dup_string (value); + break; + case PROP_PHASE2_CA_CERT: + if (priv->phase2_ca_cert) { + g_byte_array_free (priv->phase2_ca_cert, TRUE); + priv->phase2_ca_cert = NULL; + } + priv->phase2_ca_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_CA_CERT, &error); + if (error) { + g_warning ("Error setting certificate (invalid data): (%d) %s", + error->code, error->message); + g_error_free (error); + } + break; + case PROP_PHASE2_CA_PATH: + g_free (priv->phase2_ca_path); + priv->phase2_ca_path = g_value_dup_string (value); + break; + case PROP_PHASE2_CLIENT_CERT: + if (priv->phase2_client_cert) { + g_byte_array_free (priv->phase2_client_cert, TRUE); + priv->phase2_client_cert = NULL; + } + priv->phase2_client_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, &error); + if (error) { + g_warning ("Error setting certificate (invalid data): (%d) %s", + error->code, error->message); + g_error_free (error); + } + break; + case PROP_PASSWORD: + g_free (priv->password); + priv->password = g_value_dup_string (value); + break; + case PROP_PRIVATE_KEY: + if (priv->private_key) { + g_byte_array_free (priv->private_key, TRUE); + priv->private_key = NULL; + } + priv->private_key = set_cert_prop_helper (value, NM_SETTING_802_1X_PRIVATE_KEY, &error); + if (error) { + g_warning ("Error setting private key (invalid data): (%d) %s", + error->code, error->message); + g_error_free (error); + } + break; + case PROP_PRIVATE_KEY_PASSWORD: + g_free (priv->private_key_password); + priv->private_key_password = g_value_dup_string (value); + break; + case PROP_PHASE2_PRIVATE_KEY: + if (priv->phase2_private_key) { + g_byte_array_free (priv->phase2_private_key, TRUE); + priv->phase2_private_key = NULL; + } + priv->phase2_private_key = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &error); + if (error) { + g_warning ("Error setting private key (invalid data): (%d) %s", + error->code, error->message); + g_error_free (error); + } + break; + case PROP_PHASE2_PRIVATE_KEY_PASSWORD: + g_free (priv->phase2_private_key_password); + priv->phase2_private_key_password = g_value_dup_string (value); + break; + case PROP_SYSTEM_CA_CERTS: + priv->system_ca_certs = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSetting8021x *setting = NM_SETTING_802_1X (object); + NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_EAP: + g_value_set_boxed (value, priv->eap); + break; + case PROP_IDENTITY: + g_value_set_string (value, priv->identity); + break; + case PROP_ANONYMOUS_IDENTITY: + g_value_set_string (value, priv->anonymous_identity); + break; + case PROP_CA_CERT: + g_value_set_boxed (value, priv->ca_cert); + break; + case PROP_CA_PATH: + g_value_set_string (value, priv->ca_path); + break; + case PROP_CLIENT_CERT: + g_value_set_boxed (value, priv->client_cert); + break; + case PROP_PHASE1_PEAPVER: + g_value_set_string (value, priv->phase1_peapver); + break; + case PROP_PHASE1_PEAPLABEL: + g_value_set_string (value, priv->phase1_peaplabel); + break; + case PROP_PHASE1_FAST_PROVISIONING: + g_value_set_string (value, priv->phase1_fast_provisioning); + break; + case PROP_PHASE2_AUTH: + g_value_set_string (value, priv->phase2_auth); + break; + case PROP_PHASE2_AUTHEAP: + g_value_set_string (value, priv->phase2_autheap); + break; + case PROP_PHASE2_CA_CERT: + g_value_set_boxed (value, priv->phase2_ca_cert); + break; + case PROP_PHASE2_CA_PATH: + g_value_set_string (value, priv->phase2_ca_path); + break; + case PROP_PHASE2_CLIENT_CERT: + g_value_set_boxed (value, priv->phase2_client_cert); + break; + case PROP_PASSWORD: + g_value_set_string (value, priv->password); + break; + case PROP_PRIVATE_KEY: + g_value_set_boxed (value, priv->private_key); + break; + case PROP_PRIVATE_KEY_PASSWORD: + g_value_set_string (value, priv->private_key_password); + break; + case PROP_PHASE2_PRIVATE_KEY: + g_value_set_boxed (value, priv->phase2_private_key); + break; + case PROP_PHASE2_PRIVATE_KEY_PASSWORD: + g_value_set_string (value, priv->phase2_private_key_password); + break; + case PROP_SYSTEM_CA_CERTS: + g_value_set_boolean (value, priv->system_ca_certs); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + GError *error = NULL; + + g_type_class_add_private (setting_class, sizeof (NMSetting8021xPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + parent_class->verify = verify; + parent_class->need_secrets = need_secrets; + + /* Properties */ + + /** + * NMSetting8021x:eap: + * + * The allowed EAP method to be used when authenticating to the network with + * 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", and + * "fast". Each method requires different configuration using the + * properties of this object; refer to wpa_supplicant documentation for the + * allowed combinations. + **/ + g_object_class_install_property + (object_class, PROP_EAP, + _nm_param_spec_specialized (NM_SETTING_802_1X_EAP, + "EAP", + "The allowed EAP method to be used when " + "authenticating to the network with 802.1x. " + "Valid methods are: 'leap', 'md5', 'tls', 'peap', " + "'ttls', and 'fast'. Each method requires " + "different configuration using the properties of " + "this setting; refer to wpa_supplicant " + "documentation for the allowed combinations.", + DBUS_TYPE_G_LIST_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:identity: + * + * Identity string for EAP authentication methods. Often the user's + * user or login name. + **/ + g_object_class_install_property + (object_class, PROP_IDENTITY, + g_param_spec_string (NM_SETTING_802_1X_IDENTITY, + "Identity", + "Identity string for EAP authentication methods. " + "Often the user's user or login name.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:anonymous-identity: + * + * Anonymous identity string for EAP authentication methods. Used as the + * unencrypted identity with EAP types that support different tunneled + * identity like EAP-TTLS. + **/ + g_object_class_install_property + (object_class, PROP_ANONYMOUS_IDENTITY, + g_param_spec_string (NM_SETTING_802_1X_ANONYMOUS_IDENTITY, + "Anonymous identity", + "Anonymous identity string for EAP authentication " + "methods. Used as the unencrypted identity with EAP " + "types that support different tunneled identity like " + "EAP-TTLS.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:ca-cert: + * + * Contains the CA certificate if used by the EAP method specified in the + * #NMSetting8021x:eap property. Setting this property directly is + * discouraged; use the nm_setting_802_1x_set_ca_cert() function instead. + **/ + g_object_class_install_property + (object_class, PROP_CA_CERT, + _nm_param_spec_specialized (NM_SETTING_802_1X_CA_CERT, + "CA certificate", + "Contains the CA certificate if used by the EAP " + "method specified in the 'eap' property. " + "Certificate data is specified using a 'scheme'; " + "two are currently supported: blob and path. " + "When using the blob scheme (which is backwards " + "compatible with NM 0.7.x) this property should " + "be set to the certificate's DER encoded data. " + "When using the path scheme, this property should " + "be set to the full UTF-8 encoded path of the " + "certificate, prefixed with the string 'file://' " + "and ending with a terminating NULL byte. This " + "property can be unset even if the EAP method " + "supports CA certificates, but this allows " + "man-in-the-middle attacks and is NOT recommended.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:ca-path: + * + * UTF-8 encoded path to a directory containing PEM or DER formatted + * certificates to be added to the verification chain in addition to the + * certificate specified in the #NMSetting8021x:ca-cert property. + **/ + g_object_class_install_property + (object_class, PROP_CA_PATH, + g_param_spec_string (NM_SETTING_802_1X_CA_PATH, + "CA path", + "UTF-8 encoded path to a directory containing PEM or " + "DER formatted certificates to be added to the " + "verification chain in addition to the certificate " + "specified in the 'ca-cert' property.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:client-cert: + * + * Contains the client certificate if used by the EAP method specified in + * the #NMSetting8021x:eap property. Setting this property directly is + * discouraged; use the nm_setting_802_1x_set_client_cert() function instead. + **/ + g_object_class_install_property + (object_class, PROP_CLIENT_CERT, + _nm_param_spec_specialized (NM_SETTING_802_1X_CLIENT_CERT, + "Client certificate", + "Contains the client certificate if used by the " + "EAP method specified in the 'eap' property. " + "Certificate data is specified using a 'scheme'; " + "two are currently supported: blob and path. " + "When using the blob scheme (which is backwards " + "compatible with NM 0.7.x) this property should " + "be set to the certificate's DER encoded data. " + "When using the path scheme, this property should " + "be set to the full UTF-8 encoded path of the " + "certificate, prefixed with the string 'file://' " + "and ending with a terminating NULL byte.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:phase1-peapver: + * + * Forces which PEAP version is used when PEAP is set as the EAP method in + * the #NMSetting8021x:eap property. When unset, the version reported by + * the server will be used. Sometimes when using older RADIUS servers, it + * is necessary to force the client to use a particular PEAP version. To do + * so, this property may be set to "0" or "1" to force that specific PEAP + * version. + **/ + g_object_class_install_property + (object_class, PROP_PHASE1_PEAPVER, + g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPVER, + "Phase1 PEAPVER", + "Forces which PEAP version is used when PEAP is set " + "as the EAP method in 'eap' property. When unset, " + "the version reported by the server will be used. " + "Sometimes when using older RADIUS servers, it is " + "necessary to force the client to use a particular " + "PEAP version. To do so, this property may be set to " + "'0' or '1; to force that specific PEAP version.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:phase1-peaplabel: + * + * Forces use of the new PEAP label during key derivation. Some RADIUS + * servers may require forcing the new PEAP label to interoperate with + * PEAPv1. Set to "1" to force use of the new PEAP label. See the + * wpa_supplicant documentation for more details. + **/ + g_object_class_install_property + (object_class, PROP_PHASE1_PEAPLABEL, + g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPLABEL, + "Phase1 PEAP label", + "Forces use of the new PEAP label during key " + "derivation. Some RADIUS servers may require forcing " + "the new PEAP label to interoperate with PEAPv1. " + "Set to '1' to force use of the new PEAP label. See " + "the wpa_supplicant documentation for more details.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:phase1-fast-provisioning: + * + * Enables or disables in-line provisioning of EAP-FAST credentials when + * FAST is specified as the EAP method in the #NMSetting8021x:eap property. + * Recognized values are "0" (disabled), "1" (allow unauthenticated + * provisioning), "2" (allow authenticated provisioning), and "3" (allow + * both authenticated and unauthenticated provisioning). See the + * wpa_supplicant documentation for more details. + **/ + g_object_class_install_property + (object_class, PROP_PHASE1_FAST_PROVISIONING, + g_param_spec_string (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, + "Phase1 fast provisioning", + "Enables or disables in-line provisioning of EAP-FAST " + "credentials when FAST is specified as the EAP method " + "in the #NMSetting8021x:eap property. Allowed values " + "are '0' (disabled), '1' (allow unauthenticated " + "provisioning), '2' (allow authenticated provisioning), " + "and '3' (allow both authenticated and unauthenticated " + "provisioning). See the wpa_supplicant documentation " + "for more details.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:phase2-auth: + * + * Specifies the allowed "phase 2" inner non-EAP authentication methods when + * an EAP method that uses an inner TLS tunnel is specified in the + * #NMSetting8021x:eap property. Recognized non-EAP phase2 methods are + * "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", and "tls". + * Each 'phase 2' inner method requires specific parameters for successful + * authentication; see the wpa_supplicant documentation for more details. + **/ + g_object_class_install_property + (object_class, PROP_PHASE2_AUTH, + g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTH, + "Phase2 auth", + "Specifies the allowed 'phase 2' inner non-EAP " + "authentication methods when an EAP method that uses " + "an inner TLS tunnel is specified in the 'eap' " + "property. Recognized non-EAP phase2 methods are 'pap', " + "'chap', 'mschap', 'mschapv2', 'gtc', 'otp', 'md5', " + "and 'tls'. Each 'phase 2' inner method requires " + "specific parameters for successful authentication; " + "see the wpa_supplicant documentation for more details.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:phase2-autheap: + * + * Specifies the allowed "phase 2" inner EAP-based authentication methods + * when an EAP method that uses an inner TLS tunnel is specified in the + * #NMSetting8021x:eap property. Recognized EAP-based phase2 methods are + * "md5", "mschapv2", "otp", "gtc", and "tls". Each 'phase 2' inner method + * requires specific parameters for successful authentication; see the + * wpa_supplicant documentation for more details. + **/ + g_object_class_install_property + (object_class, PROP_PHASE2_AUTHEAP, + g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTHEAP, + "Phase2 autheap", + "Specifies the allowed 'phase 2' inner EAP-based " + "authentication methods when an EAP method that uses " + "an inner TLS tunnel is specified in the 'eap' " + "property. Recognized EAP-based 'phase 2' methods are " + "'md5', 'mschapv2', 'otp', 'gtc', and 'tls'. Each " + "'phase 2' inner method requires specific parameters " + "for successful authentication; see the wpa_supplicant " + "documentation for more details.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:phase2-ca-cert: + * + * Contains the CA certificate if used by the EAP method specified in the + * #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap properties. + * Setting this property directly is discouraged; use the + * nm_setting_802_1x_set_phase2_ca_cert() function instead. + **/ + g_object_class_install_property + (object_class, PROP_PHASE2_CA_CERT, + _nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_CA_CERT, + "Phase2 CA certificate", + "Contains the 'phase 2' CA certificate if used by " + "the EAP method specified in the 'phase2-auth' or " + "'phase2-autheap' properties. Certificate data " + "is specified using a 'scheme'; two are currently" + "supported: blob and path. When using the blob " + "scheme (which is backwards compatible with NM " + "0.7.x) this property should be set to the " + "certificate's DER encoded data. When using the " + "path scheme, this property should be set to the " + "full UTF-8 encoded path of the certificate, " + "prefixed with the string 'file://' and ending " + "with a terminating NULL byte. This property can " + "be unset even if the EAP method supports CA " + "certificates, but this allows man-in-the-middle " + "attacks and is NOT recommended.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:phase2-ca-path: + * + * UTF-8 encoded path to a directory containing PEM or DER formatted + * certificates to be added to the verification chain in addition to the + * certificate specified in the #NMSetting8021x:phase2-ca-cert property. + **/ + g_object_class_install_property + (object_class, PROP_PHASE2_CA_PATH, + g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_PATH, + "Phase2 auth CA path", + "UTF-8 encoded path to a directory containing PEM or " + "DER formatted certificates to be added to the " + "verification chain in addition to the certificate " + "specified in the 'phase2-ca-cert' property.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:phase2-client-cert: + * + * Contains the client certificate if used by the EAP method specified in + * the #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap + * properties. Setting this property directly is discouraged; use the + * nm_setting_802_1x_set_phase2_client_cert() function instead. + **/ + g_object_class_install_property + (object_class, PROP_PHASE2_CLIENT_CERT, + _nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_CLIENT_CERT, + "Phase2 client certificate", + "Contains the 'phase 2' client certificate if " + "used by the EAP method specified in the " + "'phase2-eap' or 'phase2-autheap' properties. " + "Certificate data is specified using a 'scheme'; " + "two are currently supported: blob and path. " + "When using the blob scheme (which is backwards " + "compatible with NM 0.7.x) this property should " + "be set to the certificate's DER encoded data. " + "When using the path scheme, this property should " + "be set to the full UTF-8 encoded path of the " + "certificate, prefixed with the string 'file://' " + "and ending with a terminating NULL byte.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSetting8021x:password: + * + * Password used for EAP authentication methods. + **/ + g_object_class_install_property + (object_class, PROP_PASSWORD, + g_param_spec_string (NM_SETTING_802_1X_PASSWORD, + "Password", + "Password used for EAP authentication methods.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSetting8021x:private-key: + * + * Contains the private key if the #NMSetting8021x:eap property is set to + * 'tls'. Setting this property directly is discouraged; use the + * nm_setting_802_1x_set_private_key() function instead. + **/ + g_object_class_install_property + (object_class, PROP_PRIVATE_KEY, + _nm_param_spec_specialized (NM_SETTING_802_1X_PRIVATE_KEY, + "Private key", + "Contains the private key when the 'eap' property " + "is set to 'tls'. Key data is specified using a " + "'scheme'; two are currently supported: blob and " + "path. When using the blob scheme and X.509 private " + "keys, this property should be set to the keys's " + "decrypted DER encoded data. When using X.509 " + "private keys with the path scheme, this property " + "should be set to the full UTF-8 encoded path of " + "the key, prefixed with the string 'file://' and " + "and ending with a terminating NULL byte. When " + "using PKCS#12 format private keys and the blob " + "scheme, this property should be set to the " + "PKCS#12 data (which is encrypted) and the " + "'private-key-password' property must be set to " + "password used to decrypt the PKCS#12 certificate " + "and key. When using PKCS#12 files and the path " + "scheme, this property should be set to the full " + "UTF-8 encoded path of the key, prefixed with the " + "string 'file://' and and ending with a " + "terminating NULL byte, and as with the blob " + "scheme the 'private-key-password' property must " + "be set to the password used to decode the PKCS#12 " + "private key and certificate.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSetting8021x:private-key-password: + * + * The password used to decrypt the private key specified in + * #NMSetting8021x:private-key when the private key either uses the path + * scheme, or if the private key is a PKCS#12 format key. Setting this + * property directly is not generally necessary except when returning + * secrets to NetworkManager; it is generally set automatically when setting + * the private key by the nm_setting_802_1x_set_private_key() function. + **/ + g_object_class_install_property + (object_class, PROP_PRIVATE_KEY_PASSWORD, + g_param_spec_string (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, + "Private key password", + "The password used to decrypt the private key " + "specified in the 'private-key' property when the " + "private key either uses the path scheme, or if the " + "private key is a PKCS#12 format key.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSetting8021x:phase2-private-key: + * + * Private key data used by "phase 2" inner authentication methods. + * + * Contains the "phase 2" inner private key if the #NMSetting8021x:auth or + * #NMSetting8021x:phase2-autheap property is set to 'tls'. Setting this + * property directly is discouraged; use the + * nm_setting_802_1x_set_phase2_private_key() function instead. + **/ + g_object_class_install_property + (object_class, PROP_PHASE2_PRIVATE_KEY, + _nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, + "Phase2 private key", + "Contains the 'phase 2' inner private key when " + "the 'phase2-eap' or 'phase2-autheap' property " + "is set to 'tls'. Key data is specified using a " + "'scheme'; two are currently supported: blob and " + "path. When using the blob scheme and X.509 private " + "keys, this property should be set to the keys's " + "decrypted DER encoded data. When using X.509 " + "private keys with the path scheme, this property " + "should be set to the full UTF-8 encoded path of " + "the key, prefixed with the string 'file://' and " + "and ending with a terminating NULL byte. When " + "using PKCS#12 format private keys and the blob " + "scheme, this property should be set to the " + "PKCS#12 data (which is encrypted) and the " + "'private-key-password' property must be set to " + "password used to decrypt the PKCS#12 certificate " + "and key. When using PKCS#12 files and the path " + "scheme, this property should be set to the full " + "UTF-8 encoded path of the key, prefixed with the " + "string 'file://' and and ending with a " + "terminating NULL byte, and as with the blob " + "scheme the 'private-key-password' property must " + "be set to the password used to decode the PKCS#12 " + "private key and certificate.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSetting8021x:phase2-private-key-password: + * + * The password used to decrypt the private key specified in + * #NMSetting8021x:phase2-private-key when the private key either uses the + * path scheme, or if the private key is a PKCS#12 format key. Setting this + * property directly is not generally necessary except when returning + * secrets to NetworkManager; it is generally set automatically when setting + * the private key by the nm_setting_802_1x_set_phase2_private_key() function. + **/ + g_object_class_install_property + (object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD, + g_param_spec_string (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, + "Phase2 private key password", + "The password used to decrypt the 'phase 2' private " + "key specified in the 'private-key' property when the " + "phase2 private key either uses the path scheme, or " + "if the phase2 private key is a PKCS#12 format key.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSetting8021x:system-ca-certs: + * + * When TRUE, overrides #NMSetting8021x:ca-path and + * #NMSetting8021x:phase2-ca-path properties using the system CA directory + * specified at configure time with the --system-ca-path switch. The + * certificates in this directory are added to the verification chain in + * addition to any certificates specified by the #NMSetting8021x:ca-cert, + * #NMSetting8021x:ca-cert-path, #NMSetting8021x:phase2-ca-cert and + * #NMSetting8021x:phase2-ca-cert-path properties. + **/ + g_object_class_install_property + (object_class, PROP_SYSTEM_CA_CERTS, + g_param_spec_boolean (NM_SETTING_802_1X_SYSTEM_CA_CERTS, + "Use system CA certificates", + "When TRUE, overrides 'ca-path' and 'phase2-ca-path' " + "properties using the system CA directory " + "specified at configure time with the " + "--system-ca-path switch. The certificates in " + "this directory are added to the verification " + "chain in addition to any certificates specified " + "by the 'ca-cert' and 'phase2-ca-cert' properties.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /* Initialize crypto lbrary. */ + if (!nm_utils_init (&error)) { + g_warning ("Couldn't initilize nm-utils/crypto system: %d %s", + error->code, error->message); + g_error_free (error); + } + +} diff --git a/libnm-util/nm-setting-8021x.h b/libnm-util/nm-setting-8021x.h new file mode 100644 index 00000000..7ee868a0 --- /dev/null +++ b/libnm-util/nm-setting-8021x.h @@ -0,0 +1,280 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2009 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_8021X_H +#define NM_SETTING_8021X_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +typedef enum { + NM_SETTING_802_1X_CK_FORMAT_UNKNOWN = 0, + NM_SETTING_802_1X_CK_FORMAT_X509, + NM_SETTING_802_1X_CK_FORMAT_RAW_KEY, + NM_SETTING_802_1X_CK_FORMAT_PKCS12 +} NMSetting8021xCKFormat; + +typedef enum { + NM_SETTING_802_1X_CK_SCHEME_UNKNOWN = 0, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + NM_SETTING_802_1X_CK_SCHEME_PATH +} NMSetting8021xCKScheme; + +#define NM_TYPE_SETTING_802_1X (nm_setting_802_1x_get_type ()) +#define NM_SETTING_802_1X(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_802_1X, NMSetting8021x)) +#define NM_SETTING_802_1X_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_802_1X, NMSetting8021xClass)) +#define NM_IS_SETTING_802_1X(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_802_1X)) +#define NM_IS_SETTING_802_1X_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_802_1X)) +#define NM_SETTING_802_1X_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_802_1X, NMSetting8021xClass)) + +#define NM_SETTING_802_1X_SETTING_NAME "802-1x" + +typedef enum +{ + NM_SETTING_802_1X_ERROR_UNKNOWN = 0, + NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, + NM_SETTING_802_1X_ERROR_MISSING_PROPERTY +} NMSetting8021xError; + +#define NM_TYPE_SETTING_802_1X_ERROR (nm_setting_802_1x_error_get_type ()) +GType nm_setting_802_1x_error_get_type (void); + +#define NM_SETTING_802_1X_ERROR nm_setting_802_1x_error_quark () +GQuark nm_setting_802_1x_error_quark (void); + + +#define NM_SETTING_802_1X_EAP "eap" +#define NM_SETTING_802_1X_IDENTITY "identity" +#define NM_SETTING_802_1X_ANONYMOUS_IDENTITY "anonymous-identity" +#define NM_SETTING_802_1X_CA_CERT "ca-cert" +#define NM_SETTING_802_1X_CA_PATH "ca-path" +#define NM_SETTING_802_1X_CLIENT_CERT "client-cert" +#define NM_SETTING_802_1X_PHASE1_PEAPVER "phase1-peapver" +#define NM_SETTING_802_1X_PHASE1_PEAPLABEL "phase1-peaplabel" +#define NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING "phase1-fast-provisioning" +#define NM_SETTING_802_1X_PHASE2_AUTH "phase2-auth" +#define NM_SETTING_802_1X_PHASE2_AUTHEAP "phase2-autheap" +#define NM_SETTING_802_1X_PHASE2_CA_CERT "phase2-ca-cert" +#define NM_SETTING_802_1X_PHASE2_CA_PATH "phase2-ca-path" +#define NM_SETTING_802_1X_PHASE2_CLIENT_CERT "phase2-client-cert" +#define NM_SETTING_802_1X_PASSWORD "password" +#define NM_SETTING_802_1X_PRIVATE_KEY "private-key" +#define NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD "private-key-password" +#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY "phase2-private-key" +#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD "phase2-private-key-password" +#define NM_SETTING_802_1X_PIN "pin" +#define NM_SETTING_802_1X_PSK "psk" +#define NM_SETTING_802_1X_SYSTEM_CA_CERTS "system-ca-certs" + +/* PRIVATE KEY NOTE: when setting PKCS#12 private keys directly via properties + * using the "blob" scheme, the data must be passed in PKCS#12 format. In this + * case, the private key password must also be passed to NetworkManager, and the + * appropriate "client-cert" (or "phase2-client-cert") property of the + * NMSetting8021x object must also contain the exact same PKCS#12 data that the + * private key will when NetworkManager requests secrets. This is because the + * PKCS#12 file contains both the private key and client certificate, so both + * properties need to be set to the same thing. When using the "path" scheme, + * just set both the private-key and client-cert properties to the same path, + * and set the private-key password correctly. + * + * When setting OpenSSL-derived "traditional" format (ie S/MIME style, not + * PKCS#8) RSA and DSA keys directly via properties with the "blob" scheme, they + * must passed to NetworkManager completely decrypted because the OpenSSL + * "traditional" format is non-standard and is not complete enough for all + * crypto libraries to use. Thus, for OpenSSL "traditional" format keys, the + * private key password is not passed to NetworkManager (because the data is + * already decrypted by the client), and the appropriate "client-cert" (or + * "phase2-client-cert") property of the NMSetting8021x object must be a valid + * client certificate. When using the "path" scheme, just set the private-key + * and client-cert properties to the paths to their respective objects, and + * set the private-key password correctly. + */ + +typedef struct { + NMSetting parent; +} NMSetting8021x; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSetting8021xClass; + +GType nm_setting_802_1x_get_type (void); + +NMSetting *nm_setting_802_1x_new (void); + +guint32 nm_setting_802_1x_get_num_eap_methods (NMSetting8021x *setting); +const char * nm_setting_802_1x_get_eap_method (NMSetting8021x *setting, guint32 i); +gboolean nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap); +void nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i); +void nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting); + +const char * nm_setting_802_1x_get_identity (NMSetting8021x *setting); + +const char * nm_setting_802_1x_get_anonymous_identity (NMSetting8021x *setting); + +gboolean nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting); +const char * nm_setting_802_1x_get_ca_path (NMSetting8021x *setting); +const char * nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting); + +NMSetting8021xCKScheme nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting); +const GByteArray * nm_setting_802_1x_get_ca_cert_blob (NMSetting8021x *setting); +const char * nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting, + const char *value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error); + +NMSetting8021xCKScheme nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting); +const GByteArray * nm_setting_802_1x_get_client_cert_blob (NMSetting8021x *setting); +const char * nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_client_cert (NMSetting8021x *setting, + const char *value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error); + +const char * nm_setting_802_1x_get_phase1_peapver (NMSetting8021x *setting); + +const char * nm_setting_802_1x_get_phase1_peaplabel (NMSetting8021x *setting); + +const char * nm_setting_802_1x_get_phase1_fast_provisioning (NMSetting8021x *setting); + +const char * nm_setting_802_1x_get_phase2_auth (NMSetting8021x *setting); + +const char * nm_setting_802_1x_get_phase2_autheap (NMSetting8021x *setting); + +NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_ca_cert_scheme (NMSetting8021x *setting); +const GByteArray * nm_setting_802_1x_get_phase2_ca_cert_blob (NMSetting8021x *setting); +const char * nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting, + const char *value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error); + +NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting); +const GByteArray * nm_setting_802_1x_get_phase2_client_cert_blob (NMSetting8021x *setting); +const char * nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting, + const char *value, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error); + +const char * nm_setting_802_1x_get_password (NMSetting8021x *setting); + +const char * nm_setting_802_1x_get_pin (NMSetting8021x *setting); + +const char * nm_setting_802_1x_get_psk (NMSetting8021x *setting); + +NMSetting8021xCKScheme nm_setting_802_1x_get_private_key_scheme (NMSetting8021x *setting); +const GByteArray * nm_setting_802_1x_get_private_key_blob (NMSetting8021x *setting); +const char * nm_setting_802_1x_get_private_key_path (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_private_key (NMSetting8021x *setting, + const char *value, + const char *password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error); +const char * nm_setting_802_1x_get_private_key_password (NMSetting8021x *setting); + +NMSetting8021xCKFormat nm_setting_802_1x_get_private_key_format (NMSetting8021x *setting); + +NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_private_key_scheme (NMSetting8021x *setting); +const GByteArray * nm_setting_802_1x_get_phase2_private_key_blob (NMSetting8021x *setting); +const char * nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting, + const char *value, + const char *password, + NMSetting8021xCKScheme scheme, + NMSetting8021xCKFormat *out_format, + GError **error); +const char * nm_setting_802_1x_get_phase2_private_key_password (NMSetting8021x *setting); + +NMSetting8021xCKFormat nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting); + + +/***** DEPRECATED; anything below will be removed in version 0.9 *****/ + +typedef enum { + NM_SETTING_802_1X_CK_TYPE_UNKNOWN = 0, + NM_SETTING_802_1X_CK_TYPE_X509, + NM_SETTING_802_1X_CK_TYPE_RAW_KEY, + NM_SETTING_802_1X_CK_TYPE_PKCS12 +} NMSetting8021xCKType; + +const GByteArray *nm_setting_802_1x_get_ca_cert (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_ca_cert_from_file (NMSetting8021x *setting, + const char *filename, + NMSetting8021xCKType *out_ck_type, + GError **error); + +const GByteArray *nm_setting_802_1x_get_client_cert (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_client_cert_from_file (NMSetting8021x *setting, + const char *filename, + NMSetting8021xCKType *out_ck_type, + GError **error); + +const GByteArray *nm_setting_802_1x_get_phase2_ca_cert (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_phase2_ca_cert_from_file (NMSetting8021x *setting, + const char *filename, + NMSetting8021xCKType *out_ck_type, + GError **error); + +const GByteArray *nm_setting_802_1x_get_phase2_client_cert (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_phase2_client_cert_from_file (NMSetting8021x *setting, + const char *filename, + NMSetting8021xCKType *out_ck_type, + GError **error); + +const GByteArray *nm_setting_802_1x_get_private_key (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_private_key_from_file (NMSetting8021x *setting, + const char *filename, + const char *password, + NMSetting8021xCKType *out_ck_type, + GError **error); + +NMSetting8021xCKType nm_setting_802_1x_get_private_key_type (NMSetting8021x *setting); + +const GByteArray *nm_setting_802_1x_get_phase2_private_key (NMSetting8021x *setting); +gboolean nm_setting_802_1x_set_phase2_private_key_from_file (NMSetting8021x *setting, + const char *filename, + const char *password, + NMSetting8021xCKType *out_ck_type, + GError **error); + +NMSetting8021xCKType nm_setting_802_1x_get_phase2_private_key_type (NMSetting8021x *setting); + +G_END_DECLS + +#endif /* NM_SETTING_8021X_H */ diff --git a/libnm-util/nm-setting-bluetooth.c b/libnm-util/nm-setting-bluetooth.c new file mode 100644 index 00000000..70840df9 --- /dev/null +++ b/libnm-util/nm-setting-bluetooth.c @@ -0,0 +1,282 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Bastien Nocera <hadess@hadess.net> + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2009 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> +#include <ctype.h> +#include <net/ethernet.h> + +#include "nm-param-spec-specialized.h" +#include "nm-dbus-glib-types.h" +#include "nm-setting-bluetooth.h" +#include "nm-setting-cdma.h" +#include "nm-setting-gsm.h" + +GQuark +nm_setting_bluetooth_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-bluetooth-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_bluetooth_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + ENUM_ENTRY (NM_SETTING_BLUETOOTH_ERROR_UNKNOWN, "UnknownError"), + ENUM_ENTRY (NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, "InvalidProperty"), + ENUM_ENTRY (NM_SETTING_BLUETOOTH_ERROR_MISSING_PROPERTY, "MissingProperty"), + ENUM_ENTRY (NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND, "TypeSettingNotFound"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingBluetoothError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING) + +#define NM_SETTING_BLUETOOTH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothPrivate)) + +typedef struct { + GByteArray *bdaddr; + char *type; +} NMSettingBluetoothPrivate; + +enum { + PROP_0, + PROP_BDADDR, + PROP_TYPE, + + LAST_PROP +}; + +NMSetting *nm_setting_bluetooth_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_BLUETOOTH, NULL); +} + +const char * +nm_setting_bluetooth_get_connection_type (NMSettingBluetooth *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BLUETOOTH (setting), 0); + + return NM_SETTING_BLUETOOTH_GET_PRIVATE (setting)->type; +} + +const GByteArray * +nm_setting_bluetooth_get_bdaddr (NMSettingBluetooth *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BLUETOOTH (setting), NULL); + + return NM_SETTING_BLUETOOTH_GET_PRIVATE (setting)->bdaddr; +} + +static gint +find_setting_by_name (gconstpointer a, gconstpointer b) +{ + NMSetting *setting = NM_SETTING (a); + const char *str = (const char *) b; + + return strcmp (nm_setting_get_name (setting), str); +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE (setting); + + if (!priv->bdaddr) { + g_set_error (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_MISSING_PROPERTY, + NM_SETTING_BLUETOOTH_BDADDR); + return FALSE; + } + + if (priv->bdaddr && priv->bdaddr->len != ETH_ALEN) { + g_set_error (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, + NM_SETTING_BLUETOOTH_BDADDR); + return FALSE; + } + + if (!priv->type) { + g_set_error (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_MISSING_PROPERTY, + NM_SETTING_BLUETOOTH_TYPE); + return FALSE; + } else if (!g_str_equal (priv->type, NM_SETTING_BLUETOOTH_TYPE_DUN) && + !g_str_equal (priv->type, NM_SETTING_BLUETOOTH_TYPE_PANU)) { + g_set_error (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, + NM_SETTING_BLUETOOTH_TYPE); + return FALSE; + } + + /* Make sure the corresponding 'type' setting is present */ + if ( all_settings + && !strcmp (priv->type, NM_SETTING_BLUETOOTH_TYPE_DUN)) { + gboolean gsm = FALSE, cdma = FALSE; + + gsm = !!g_slist_find_custom (all_settings, + (gpointer) NM_SETTING_GSM_SETTING_NAME, + find_setting_by_name); + cdma = !!g_slist_find_custom (all_settings, + (gpointer) NM_SETTING_CDMA_SETTING_NAME, + find_setting_by_name); + + if (!gsm && !cdma) { + g_set_error (error, + NM_SETTING_BLUETOOTH_ERROR, + NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND, + NM_SETTING_BLUETOOTH_TYPE); + return FALSE; + } + } + /* PANU doesn't need a 'type' setting since no further configuration + * is required at the interface level. + */ + + return TRUE; +} + +static void +nm_setting_bluetooth_init (NMSettingBluetooth *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_BLUETOOTH_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE (object); + + if (priv->bdaddr) + g_byte_array_free (priv->bdaddr, TRUE); + + G_OBJECT_CLASS (nm_setting_bluetooth_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BDADDR: + if (priv->bdaddr) + g_byte_array_free (priv->bdaddr, TRUE); + priv->bdaddr = g_value_dup_boxed (value); + break; + case PROP_TYPE: + g_free (priv->type); + priv->type = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingBluetooth *setting = NM_SETTING_BLUETOOTH (object); + + switch (prop_id) { + case PROP_BDADDR: + g_value_set_boxed (value, nm_setting_bluetooth_get_bdaddr (setting)); + break; + case PROP_TYPE: + g_value_set_string (value, nm_setting_bluetooth_get_connection_type (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingBluetoothPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ + + /** + * NMSettingBluetooth:bdaddr: + * + * The Bluetooth address of the device. + **/ + g_object_class_install_property + (object_class, PROP_BDADDR, + _nm_param_spec_specialized (NM_SETTING_BLUETOOTH_BDADDR, + "Bluetooth address", + "The Bluetooth address of the device", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingBluetooth:type: + * + * Either 'dun' for Dial-Up Networking connections (not yet supported) or + * 'panu' for Personal Area Networking connections. + **/ + g_object_class_install_property + (object_class, PROP_TYPE, + g_param_spec_string (NM_SETTING_BLUETOOTH_TYPE, + "Connection type", + "Either '" NM_SETTING_BLUETOOTH_TYPE_DUN "' for " + "Dial-Up Networking connections (not yet supported) " + " or '" NM_SETTING_BLUETOOTH_TYPE_PANU "' for " + "Personal Area Networking connections.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); +} diff --git a/libnm-util/nm-setting-bluetooth.h b/libnm-util/nm-setting-bluetooth.h new file mode 100644 index 00000000..e41183bc --- /dev/null +++ b/libnm-util/nm-setting-bluetooth.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Bastien Nocera <hadess@hadess.net> + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2009 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_BLUETOOTH_H +#define NM_SETTING_BLUETOOTH_H + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_BLUETOOTH (nm_setting_bluetooth_get_type ()) +#define NM_SETTING_BLUETOOTH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetooth)) +#define NM_SETTING_BLUETOOTH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothClass)) +#define NM_IS_SETTING_BLUETOOTH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_BLUETOOTH)) +#define NM_IS_SETTING_BLUETOOTH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_BLUETOOTH)) +#define NM_SETTING_BLUETOOTH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothClass)) + +#define NM_SETTING_BLUETOOTH_SETTING_NAME "bluetooth" + +typedef enum +{ + NM_SETTING_BLUETOOTH_ERROR_UNKNOWN = 0, + NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY, + NM_SETTING_BLUETOOTH_ERROR_MISSING_PROPERTY, + NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND, +} NMSettingBluetoothError; + +#define NM_TYPE_SETTING_BLUETOOTH_ERROR (nm_setting_bluetooth_error_get_type ()) +GType nm_setting_bluetooth_error_get_type (void); + +#define NM_SETTING_BLUETOOTH_ERROR nm_setting_bluetooth_error_quark () +GQuark nm_setting_bluetooth_error_quark (void); + +#define NM_SETTING_BLUETOOTH_BDADDR "bdaddr" +#define NM_SETTING_BLUETOOTH_TYPE "type" + +#define NM_SETTING_BLUETOOTH_TYPE_DUN "dun" +#define NM_SETTING_BLUETOOTH_TYPE_PANU "panu" + +typedef struct { + NMSetting parent; +} NMSettingBluetooth; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingBluetoothClass; + +GType nm_setting_bluetooth_get_type (void); + +NMSetting * nm_setting_bluetooth_new (void); +const GByteArray *nm_setting_bluetooth_get_bdaddr (NMSettingBluetooth *setting); +const char * nm_setting_bluetooth_get_connection_type (NMSettingBluetooth *setting); + +G_END_DECLS + +#endif /* NM_SETTING_BLUETOOTH_H */ diff --git a/libnm-util/nm-setting-cdma.c b/libnm-util/nm-setting-cdma.c new file mode 100644 index 00000000..7255eb91 --- /dev/null +++ b/libnm-util/nm-setting-cdma.c @@ -0,0 +1,363 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + */ + +#include <string.h> +#include "nm-setting-cdma.h" +#include "nm-setting-serial.h" +#include "nm-utils.h" + +/** + * SECTION:nm-setting-cdma + * @short_description: Describes CDMA-based mobile broadband properties + * @include: nm-setting-cdma.h + * + * The #NMSettingCdma object is a #NMSetting subclass that describes + * properties that allow connections to IS-95-based mobile broadband + * networks, including those using CDMA2000/EVDO technology. + */ + +/** + * nm_setting_cdma_error_quark: + * + * Registers an error quark for #NMSettingCdma if necessary. + * + * Returns: the error quark used for #NMSettingCdma errors. + **/ +GQuark +nm_setting_cdma_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-cdma-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_cdma_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_CDMA_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_CDMA_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_CDMA_ERROR_MISSING_PROPERTY, "MissingProperty"), + /* The required serial setting is missing */ + ENUM_ENTRY (NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING, "MissingSerialSetting"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingCdmaError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING) + +#define NM_SETTING_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CDMA, NMSettingCdmaPrivate)) + +typedef struct { + char *number; /* For dialing, duh */ + char *username; + char *password; +} NMSettingCdmaPrivate; + +enum { + PROP_0, + PROP_NUMBER, + PROP_USERNAME, + PROP_PASSWORD, + + LAST_PROP +}; + +/** + * nm_setting_cdma_new: + * + * Creates a new #NMSettingCdma object with default values. + * + * Returns: the new empty #NMSettingCdma object + **/ +NMSetting * +nm_setting_cdma_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_CDMA, NULL); +} + +/** + * nm_setting_cdma_get_number: + * @setting: the #NMSettingCdma + * + * Returns: the #NMSettingCdma:number property of the setting + **/ +const char * +nm_setting_cdma_get_number (NMSettingCdma *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CDMA (setting), NULL); + + return NM_SETTING_CDMA_GET_PRIVATE (setting)->number; +} + +/** + * nm_setting_cdma_get_username: + * @setting: the #NMSettingCdma + * + * Returns: the #NMSettingCdma:username property of the setting + **/ +const char * +nm_setting_cdma_get_username (NMSettingCdma *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CDMA (setting), NULL); + + return NM_SETTING_CDMA_GET_PRIVATE (setting)->username; +} + +/** + * nm_setting_cdma_get_password: + * @setting: the #NMSettingCdma + * + * Returns: the #NMSettingCdma:password property of the setting + **/ +const char * +nm_setting_cdma_get_password (NMSettingCdma *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CDMA (setting), NULL); + + return NM_SETTING_CDMA_GET_PRIVATE (setting)->password; +} + +static gint +find_setting_by_name (gconstpointer a, gconstpointer b) +{ + NMSetting *setting = NM_SETTING (a); + const char *str = (const char *) b; + + return strcmp (nm_setting_get_name (setting), str); +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE (setting); + + /* Serial connections require a PPP setting */ + if (all_settings && + !g_slist_find_custom (all_settings, NM_SETTING_SERIAL_SETTING_NAME, find_setting_by_name)) { + g_set_error (error, + NM_SETTING_CDMA_ERROR, + NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING, + NULL); + return FALSE; + } + + if (!priv->number) { + g_set_error (error, + NM_SETTING_CDMA_ERROR, + NM_SETTING_CDMA_ERROR_MISSING_PROPERTY, + NM_SETTING_CDMA_NUMBER); + return FALSE; + } else if (!strlen (priv->number)) { + g_set_error (error, + NM_SETTING_CDMA_ERROR, + NM_SETTING_CDMA_ERROR_INVALID_PROPERTY, + NM_SETTING_CDMA_NUMBER); + return FALSE; + } + + if (priv->username && !strlen (priv->username)) { + g_set_error (error, + NM_SETTING_CDMA_ERROR, + NM_SETTING_CDMA_ERROR_INVALID_PROPERTY, + NM_SETTING_CDMA_USERNAME); + return FALSE; + } + + if (priv->password && !strlen (priv->password)) { + g_set_error (error, + NM_SETTING_CDMA_ERROR, + NM_SETTING_CDMA_ERROR_INVALID_PROPERTY, + NM_SETTING_CDMA_PASSWORD); + return FALSE; + } + + return TRUE; +} + +static GPtrArray * +need_secrets (NMSetting *setting) +{ + NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE (setting); + GPtrArray *secrets = NULL; + + if (priv->password) + return NULL; + + if (priv->username) { + secrets = g_ptr_array_sized_new (1); + g_ptr_array_add (secrets, NM_SETTING_CDMA_PASSWORD); + } + + return secrets; +} + +static void +nm_setting_cdma_init (NMSettingCdma *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_CDMA_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE (object); + + g_free (priv->number); + g_free (priv->username); + g_free (priv->password); + + G_OBJECT_CLASS (nm_setting_cdma_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_NUMBER: + g_free (priv->number); + priv->number = g_value_dup_string (value); + break; + case PROP_USERNAME: + g_free (priv->username); + priv->username = g_value_dup_string (value); + break; + case PROP_PASSWORD: + g_free (priv->password); + priv->password = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingCdma *setting = NM_SETTING_CDMA (object); + + switch (prop_id) { + case PROP_NUMBER: + g_value_set_string (value, nm_setting_cdma_get_number (setting)); + break; + case PROP_USERNAME: + g_value_set_string (value, nm_setting_cdma_get_username (setting)); + break; + case PROP_PASSWORD: + g_value_set_string (value, nm_setting_cdma_get_password (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingCdmaPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + parent_class->need_secrets = need_secrets; + + /* Properties */ + + /** + * NMSettingCdma:number: + * + * The number to dial to establish the connection to the CDMA-based mobile + * broadband network, if any. If not specified, the default number (#777) + * is used when required. + **/ + g_object_class_install_property + (object_class, PROP_NUMBER, + g_param_spec_string (NM_SETTING_CDMA_NUMBER, + "Number", + "Number to dial when establishing a PPP data session " + "with the CDMA-based mobile broadband network. If not " + "specified, the default number (#777) is used when " + "required.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingCdma:username: + * + * The username used to authenticate with the network, if required. Many + * providers do not require a username, or accept any username. But if a + * username is required, it is specified here. + **/ + g_object_class_install_property + (object_class, PROP_USERNAME, + g_param_spec_string (NM_SETTING_CDMA_USERNAME, + "Username", + "Username used to authenticate with the network, if " + "required. Note that many providers do not require " + "a username or accept any username.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingCdma:password: + * + * The password used to authenticate with the network, if required. Many + * providers do not require a password, or accept any password. But if a + * password is required, it is specified here. + **/ + g_object_class_install_property + (object_class, PROP_PASSWORD, + g_param_spec_string (NM_SETTING_CDMA_PASSWORD, + "Password", + "Password used to authenticate with the network, if " + "required. Note that many providers do not require " + "a password or accept any password.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); +} diff --git a/libnm-util/nm-setting-cdma.h b/libnm-util/nm-setting-cdma.h new file mode 100644 index 00000000..8a6c4505 --- /dev/null +++ b/libnm-util/nm-setting-cdma.h @@ -0,0 +1,83 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_CDMA_H +#define NM_SETTING_CDMA_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_CDMA (nm_setting_cdma_get_type ()) +#define NM_SETTING_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_CDMA, NMSettingCdma)) +#define NM_SETTING_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_CDMA, NMSettingCdmaClass)) +#define NM_IS_SETTING_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_CDMA)) +#define NM_IS_SETTING_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_CDMA)) +#define NM_SETTING_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_CDMA, NMSettingCdmaClass)) + +#define NM_SETTING_CDMA_SETTING_NAME "cdma" + +typedef enum +{ + NM_SETTING_CDMA_ERROR_UNKNOWN = 0, + NM_SETTING_CDMA_ERROR_INVALID_PROPERTY, + NM_SETTING_CDMA_ERROR_MISSING_PROPERTY, + NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING +} NMSettingCdmaError; + +#define NM_TYPE_SETTING_CDMA_ERROR (nm_setting_cdma_error_get_type ()) +GType nm_setting_cdma_error_get_type (void); + +#define NM_SETTING_CDMA_ERROR nm_setting_cdma_error_quark () +GQuark nm_setting_cdma_error_quark (void); + +#define NM_SETTING_CDMA_NUMBER "number" +#define NM_SETTING_CDMA_USERNAME "username" +#define NM_SETTING_CDMA_PASSWORD "password" + +typedef struct { + NMSetting parent; +} NMSettingCdma; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingCdmaClass; + +GType nm_setting_cdma_get_type (void); + +NMSetting *nm_setting_cdma_new (void); +const char *nm_setting_cdma_get_number (NMSettingCdma *setting); +const char *nm_setting_cdma_get_username (NMSettingCdma *setting); +const char *nm_setting_cdma_get_password (NMSettingCdma *setting); + +G_END_DECLS + +#endif /* NM_SETTING_CDMA_H */ diff --git a/libnm-util/nm-setting-connection.c b/libnm-util/nm-setting-connection.c new file mode 100644 index 00000000..65f613eb --- /dev/null +++ b/libnm-util/nm-setting-connection.c @@ -0,0 +1,521 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> +#include <ctype.h> +#include "nm-setting-connection.h" + +/** + * SECTION:nm-setting-connection + * @short_description: Describes general connection properties + * @include: nm-setting-connection.h + * + * The #NMSettingConnection object is a #NMSetting subclass that describes + * properties that apply to all #NMConnection objects, regardless of what type + * of network connection they describe. Each #NMConnection object must contain + * a #NMSettingConnection setting. + **/ + +/** + * nm_setting_connection_error_quark: + * + * Registers an error quark for #NMSettingConnection if necessary. + * + * Returns: the error quark used for #NMSettingConnection errors. + **/ +GQuark +nm_setting_connection_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-connection-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_connection_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + ENUM_ENTRY (NM_SETTING_CONNECTION_ERROR_UNKNOWN, "UnknownError"), + ENUM_ENTRY (NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY, "InvalidProperty"), + ENUM_ENTRY (NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY, "MissingProperty"), + ENUM_ENTRY (NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND, "TypeSettingNotFound"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingConnectionError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING) + +#define NM_SETTING_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionPrivate)) + +typedef struct { + char *id; + char *uuid; + char *type; + gboolean autoconnect; + guint64 timestamp; + gboolean read_only; +} NMSettingConnectionPrivate; + +enum { + PROP_0, + PROP_ID, + PROP_UUID, + PROP_TYPE, + PROP_AUTOCONNECT, + PROP_TIMESTAMP, + PROP_READ_ONLY, + + LAST_PROP +}; + +/** + * nm_setting_connection_new: + * + * Creates a new #NMSettingConnection object with default values. + * + * Returns: the new empty #NMSettingConnection object + **/ +NMSetting *nm_setting_connection_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_CONNECTION, NULL); +} + +/** + * nm_setting_connection_get_id: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:id property of the connection. + * + * Returns: the connection ID + **/ +const char * +nm_setting_connection_get_id (NMSettingConnection *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->id; +} + +/** + * nm_setting_connection_get_uuid: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:uuid property of the connection. + * + * Returns: the connection UUID + **/ +const char * +nm_setting_connection_get_uuid (NMSettingConnection *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->uuid; +} + +/** + * nm_setting_connection_get_connection_type: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:type property of the connection. + * + * Returns: the connection type + **/ +const char * +nm_setting_connection_get_connection_type (NMSettingConnection *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL); + + return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->type; +} + +/** + * nm_setting_connection_get_autoconnect: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:autoconnect property of the connection. + * + * Returns: the connection's autoconnect behavior + **/ +gboolean +nm_setting_connection_get_autoconnect (NMSettingConnection *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE); + + return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->autoconnect; +} + +/** + * nm_setting_connection_get_timestamp: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:timestamp property of the connection. + * + * Returns: the connection's timestamp + **/ +guint64 +nm_setting_connection_get_timestamp (NMSettingConnection *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0); + + return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->timestamp; +} + +/** + * nm_setting_connection_get_read_only: + * @setting: the #NMSettingConnection + * + * Returns the #NMSettingConnection:read-only property of the connection. + * + * Returns: %TRUE if the connection is read-only, %FALSE if it is not + **/ +gboolean +nm_setting_connection_get_read_only (NMSettingConnection *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), TRUE); + + return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->read_only; +} + +static gint +find_setting_by_name (gconstpointer a, gconstpointer b) +{ + NMSetting *setting = NM_SETTING (a); + const char *str = (const char *) b; + + return strcmp (nm_setting_get_name (setting), str); +} + +static gboolean +validate_uuid (const char *uuid) +{ + int i; + + if (!uuid || !strlen (uuid)) + return FALSE; + + for (i = 0; i < strlen (uuid); i++) { + if (!isxdigit (uuid[i]) && (uuid[i] != '-')) + return FALSE; + } + + return TRUE; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting); + + if (!priv->id) { + g_set_error (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY, + NM_SETTING_CONNECTION_ID); + return FALSE; + } else if (!strlen (priv->id)) { + g_set_error (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY, + NM_SETTING_CONNECTION_ID); + return FALSE; + } + + if (!priv->uuid) { + g_set_error (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY, + NM_SETTING_CONNECTION_UUID); + return FALSE; + } else if (!validate_uuid (priv->uuid)) { + g_set_error (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY, + NM_SETTING_CONNECTION_UUID); + return FALSE; + } + + if (!priv->type) { + g_set_error (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY, + NM_SETTING_CONNECTION_TYPE); + return FALSE; + } else if (!strlen (priv->type)) { + g_set_error (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY, + NM_SETTING_CONNECTION_TYPE); + return FALSE; + } + + /* Make sure the corresponding 'type' item is present */ + if (all_settings && !g_slist_find_custom (all_settings, priv->type, find_setting_by_name)) { + g_set_error (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND, + NM_SETTING_CONNECTION_TYPE); + return FALSE; + } + + return TRUE; +} + +static void +nm_setting_connection_init (NMSettingConnection *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_CONNECTION_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (object); + + g_free (priv->id); + g_free (priv->uuid); + g_free (priv->type); + + G_OBJECT_CLASS (nm_setting_connection_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_ID: + g_free (priv->id); + priv->id = g_value_dup_string (value); + break; + case PROP_UUID: + g_free (priv->uuid); + priv->uuid = g_value_dup_string (value); + break; + case PROP_TYPE: + g_free (priv->type); + priv->type = g_value_dup_string (value); + break; + case PROP_AUTOCONNECT: + priv->autoconnect = g_value_get_boolean (value); + break; + case PROP_TIMESTAMP: + priv->timestamp = g_value_get_uint64 (value); + break; + case PROP_READ_ONLY: + priv->read_only = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingConnection *setting = NM_SETTING_CONNECTION (object); + + switch (prop_id) { + case PROP_ID: + g_value_set_string (value, nm_setting_connection_get_id (setting)); + break; + case PROP_UUID: + g_value_set_string (value, nm_setting_connection_get_uuid (setting)); + break; + case PROP_TYPE: + g_value_set_string (value, nm_setting_connection_get_connection_type (setting)); + break; + case PROP_AUTOCONNECT: + g_value_set_boolean (value, nm_setting_connection_get_autoconnect (setting)); + break; + case PROP_TIMESTAMP: + g_value_set_uint64 (value, nm_setting_connection_get_timestamp (setting)); + break; + case PROP_READ_ONLY: + g_value_set_boolean (value, nm_setting_connection_get_read_only (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingConnectionPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ + + /** + * NMSettingConnection:id: + * + * A human readable unique idenfier for the connection, like "Work WiFi" or + * "T-Mobile 3G". + **/ + g_object_class_install_property + (object_class, PROP_ID, + g_param_spec_string (NM_SETTING_CONNECTION_ID, + "ID", + "User-readable connection identifier/name. Must be " + "one or more characters and may change over the lifetime " + "of the connection if the user decides to rename it.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingConnection:uuid: + * + * A universally unique idenfier for the connection, for example generated + * with libuuid. Should be assigned when the connection is created, and + * never changed as long as the connection still applies to the same + * network. For example, should not be changed when the + * #NMSettingConnection:id or #NMSettingIP4Config changes, but might need + * to be re-created when the WiFi SSID, mobile broadband network provider, + * or #NMSettingConnection:type changes. + * + * The UUID must be in the format '2815492f-7e56-435e-b2e9-246bd7cdc664' + * (ie, contains only hexadecimal characters and '-'). A suitable UUID may + * be generated by nm_utils_uuid_generate() or + * nm_utils_uuid_generate_from_string(). + **/ + g_object_class_install_property + (object_class, PROP_UUID, + g_param_spec_string (NM_SETTING_CONNECTION_UUID, + "UUID", + "Universally unique connection identifier. Must be " + "in the format '2815492f-7e56-435e-b2e9-246bd7cdc664' " + "(ie, contains only hexadecimal characters and '-'). " + "The UUID should be assigned when the connection is " + "created and never changed as long as the connection " + "still applies to the same network. For example, " + "it should not be changed when the user changes the " + "connection's 'id', but should be recreated when the " + "WiFi SSID, mobile broadband network provider, or the " + "connection type changes.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingConnection:type: + * + * The general hardware type of the device used for the network connection, + * contains the name of the #NMSetting object that describes that hardware + * type's parameters. For example, for WiFi devices, the name of the + * #NMSettingWireless setting. + **/ + g_object_class_install_property + (object_class, PROP_TYPE, + g_param_spec_string (NM_SETTING_CONNECTION_TYPE, + "Type", + "Base type of the connection. For hardware-dependent " + "connections, should contain the setting name of the " + "hardware-type specific setting (ie, '802-3-ethernet' " + "or '802-11-wireless' or 'bluetooth', etc), and for " + "non-hardware dependent connections like VPN or " + "otherwise, should contain the setting name of that " + "setting type (ie, 'vpn' or 'bridge', etc).", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingConnection:autoconnect: + * + * Whether or not the connection should be automatically connected by + * NetworkManager when the resources for the connection are available. + * %TRUE to automatically activate the connection, %FALSE to require manual + * intervention to activate the connection. Defaults to %TRUE. + **/ + g_object_class_install_property + (object_class, PROP_AUTOCONNECT, + g_param_spec_boolean (NM_SETTING_CONNECTION_AUTOCONNECT, + "Autoconnect", + "If TRUE, NetworkManager will activate this connection " + "when its network resources are available. If FALSE, " + "the connection must be manually activated by the user " + "or some other mechanism.", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingConnection:timestamp: + * + * The time, in seconds since the Unix Epoch, that the connection was last + * _successfully_ fully activated. + **/ + g_object_class_install_property + (object_class, PROP_TIMESTAMP, + g_param_spec_uint64 (NM_SETTING_CONNECTION_TIMESTAMP, + "Timestamp", + "Timestamp (in seconds since the Unix Epoch) that the " + "connection was last successfully activated. Settings " + "services should update the connection timestamp " + "periodically when the connection is active to ensure " + "that an active connection has the latest timestamp.", + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingConnection:read-only: + * + * %TRUE if the connection can be modified using the providing settings + * service's D-Bus interface with the right privileges, or %FALSE + * if the connection is read-only and cannot be modified. + **/ + g_object_class_install_property + (object_class, PROP_READ_ONLY, + g_param_spec_boolean (NM_SETTING_CONNECTION_READ_ONLY, + "Read-Only", + "If TRUE, the connection is read-only and cannot be " + "changed by the user or any other mechanism. This is " + "normally set for system connections whose plugin " + "cannot yet write updated connections back out.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); +} diff --git a/libnm-util/nm-setting-connection.h b/libnm-util/nm-setting-connection.h new file mode 100644 index 00000000..6dedca22 --- /dev/null +++ b/libnm-util/nm-setting-connection.h @@ -0,0 +1,110 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_CONNECTION_H +#define NM_SETTING_CONNECTION_H + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_CONNECTION (nm_setting_connection_get_type ()) +#define NM_SETTING_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_CONNECTION, NMSettingConnection)) +#define NM_SETTING_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionClass)) +#define NM_IS_SETTING_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_CONNECTION)) +#define NM_IS_SETTING_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_CONNECTION)) +#define NM_SETTING_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionClass)) + +#define NM_SETTING_CONNECTION_SETTING_NAME "connection" + +/** + * NMSettingConnectionError: + * @NM_SETTING_CONNECTION_ERROR_UNKNOWN: unknown or unclassified error + * @NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY: the property's value is + * invalid + * @NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY: a required property is not + * present + * @NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND: the #NMSetting object + * referenced by the setting name contained in the + * #NMSettingConnection:type property was not present in the #NMConnection + * + * Describes errors that may result from operations involving a + * #NMSettingConnection. + * + **/ +typedef enum +{ + NM_SETTING_CONNECTION_ERROR_UNKNOWN = 0, + NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY, + NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY, + NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND +} NMSettingConnectionError; + +#define NM_TYPE_SETTING_CONNECTION_ERROR (nm_setting_connection_error_get_type ()) +GType nm_setting_connection_error_get_type (void); + +#define NM_SETTING_CONNECTION_ERROR nm_setting_connection_error_quark () +GQuark nm_setting_connection_error_quark (void); + +#define NM_SETTING_CONNECTION_ID "id" +#define NM_SETTING_CONNECTION_UUID "uuid" +#define NM_SETTING_CONNECTION_TYPE "type" +#define NM_SETTING_CONNECTION_AUTOCONNECT "autoconnect" +#define NM_SETTING_CONNECTION_TIMESTAMP "timestamp" +#define NM_SETTING_CONNECTION_READ_ONLY "read-only" + +/** + * NMSettingConnection: + * + * The NMSettingConnection struct contains only private data. + * It should only be accessed through the functions described below. + */ +typedef struct { + NMSetting parent; +} NMSettingConnection; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingConnectionClass; + +GType nm_setting_connection_get_type (void); + +NMSetting * nm_setting_connection_new (void); +const char *nm_setting_connection_get_id (NMSettingConnection *setting); +const char *nm_setting_connection_get_uuid (NMSettingConnection *setting); +const char *nm_setting_connection_get_connection_type (NMSettingConnection *setting); +gboolean nm_setting_connection_get_autoconnect (NMSettingConnection *setting); +guint64 nm_setting_connection_get_timestamp (NMSettingConnection *setting); +gboolean nm_setting_connection_get_read_only (NMSettingConnection *setting); + +G_END_DECLS + +#endif /* NM_SETTING_CONNECTION_H */ diff --git a/libnm-util/nm-setting-gsm.c b/libnm-util/nm-setting-gsm.c new file mode 100644 index 00000000..4b4560cd --- /dev/null +++ b/libnm-util/nm-setting-gsm.c @@ -0,0 +1,656 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2010 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> +#include <ctype.h> +#include "nm-setting-gsm.h" +#include "nm-setting-serial.h" +#include "nm-utils.h" + +GQuark +nm_setting_gsm_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-gsm-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_gsm_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_GSM_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_GSM_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_GSM_ERROR_MISSING_PROPERTY, "MissingProperty"), + /* The required serial setting is missing */ + ENUM_ENTRY (NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING, "MissingSerialSetting"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingGsmError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING) + +#define NM_SETTING_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GSM, NMSettingGsmPrivate)) + +typedef struct { + char *number; /* For dialing, duh */ + char *username; + char *password; + + char *apn; /* NULL for dynamic */ + char *network_id; /* for manual registration or NULL for automatic */ + int network_type; /* One of the NM_SETTING_GSM_NETWORK_TYPE_* */ + guint32 allowed_bands; /* A bitfield of NM_SETTING_GSM_BAND_* */ + + char *pin; + + gboolean home_only; +} NMSettingGsmPrivate; + +enum { + PROP_0, + PROP_NUMBER, + PROP_USERNAME, + PROP_PASSWORD, + PROP_APN, + PROP_NETWORK_ID, + PROP_NETWORK_TYPE, + PROP_BAND, + PROP_PIN, + PROP_PUK, + PROP_ALLOWED_BANDS, + PROP_HOME_ONLY, + + LAST_PROP +}; + +NMSetting * +nm_setting_gsm_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_GSM, NULL); +} + +static gint +find_setting_by_name (gconstpointer a, gconstpointer b) +{ + NMSetting *setting = NM_SETTING (a); + const char *str = (const char *) b; + + return strcmp (nm_setting_get_name (setting), str); +} + +const char * +nm_setting_gsm_get_number (NMSettingGsm *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE (setting)->number; +} + +const char * +nm_setting_gsm_get_username (NMSettingGsm *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE (setting)->username; +} + +const char * +nm_setting_gsm_get_password (NMSettingGsm *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE (setting)->password; +} + +const char * +nm_setting_gsm_get_apn (NMSettingGsm *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE (setting)->apn; +} + +const char * +nm_setting_gsm_get_network_id (NMSettingGsm *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE (setting)->network_id; +} + +int +nm_setting_gsm_get_network_type (NMSettingGsm *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_GSM (setting), -1); + + return NM_SETTING_GSM_GET_PRIVATE (setting)->network_type; +} + +int +nm_setting_gsm_get_band (NMSettingGsm *setting) +{ + g_warning ("Tried to get deprecated property " NM_SETTING_GSM_SETTING_NAME "/" NM_SETTING_GSM_BAND); + return -1; +} + +guint32 +nm_setting_gsm_get_allowed_bands (NMSettingGsm *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NM_SETTING_GSM_BAND_UNKNOWN); + + return NM_SETTING_GSM_GET_PRIVATE (setting)->allowed_bands; +} + +const char * +nm_setting_gsm_get_pin (NMSettingGsm *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL); + + return NM_SETTING_GSM_GET_PRIVATE (setting)->pin; +} + +const char * +nm_setting_gsm_get_puk (NMSettingGsm *setting) +{ + g_warning ("Tried to get deprecated property " NM_SETTING_GSM_SETTING_NAME "/" NM_SETTING_GSM_PUK); + return NULL; +} + +gboolean +nm_setting_gsm_get_home_only (NMSettingGsm *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_GSM (setting), FALSE); + + return NM_SETTING_GSM_GET_PRIVATE (setting)->home_only; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE (setting); + + /* Serial connections require a PPP setting */ + if (all_settings && + !g_slist_find_custom (all_settings, NM_SETTING_SERIAL_SETTING_NAME, find_setting_by_name)) { + g_set_error (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING, + NULL); + return FALSE; + } + + if (!priv->number) { + g_set_error (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_MISSING_PROPERTY, + NM_SETTING_GSM_NUMBER); + return FALSE; + } else if (!strlen (priv->number)) { + g_set_error (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_INVALID_PROPERTY, + NM_SETTING_GSM_NUMBER); + return FALSE; + } + + if (priv->apn && (strlen (priv->apn) < 1 || strchr (priv->apn, '"'))) { + g_set_error (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_INVALID_PROPERTY, + NM_SETTING_GSM_APN); + return FALSE; + } + + if (priv->username && !strlen (priv->username)) { + g_set_error (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_INVALID_PROPERTY, + NM_SETTING_GSM_USERNAME); + return FALSE; + } + + if (priv->password && !strlen (priv->password)) { + g_set_error (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_INVALID_PROPERTY, + NM_SETTING_GSM_USERNAME); + return FALSE; + } + + if (priv->network_id) { + guint32 nid_len = strlen (priv->network_id); + guint32 i; + + /* Accept both 5 and 6 digit MCC/MNC codes */ + if ((nid_len < 5) || (nid_len > 6)) { + g_set_error (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_INVALID_PROPERTY, + NM_SETTING_GSM_NETWORK_ID); + return FALSE; + } + + for (i = 0; i < nid_len; i++) { + if (!isdigit (priv->network_id[i])) { + g_set_error (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_INVALID_PROPERTY, + NM_SETTING_GSM_NETWORK_ID); + return FALSE; + } + } + } + + return TRUE; +} + +static GPtrArray * +need_secrets (NMSetting *setting) +{ + NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE (setting); + GPtrArray *secrets = NULL; + + if (priv->password) + return NULL; + + if (priv->username) { + secrets = g_ptr_array_sized_new (1); + g_ptr_array_add (secrets, NM_SETTING_GSM_PASSWORD); + } + + return secrets; +} + +static void +nm_setting_gsm_init (NMSettingGsm *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_GSM_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE (object); + + g_free (priv->number); + g_free (priv->username); + g_free (priv->password); + g_free (priv->apn); + g_free (priv->network_id); + g_free (priv->pin); + + G_OBJECT_CLASS (nm_setting_gsm_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE (object); + const char *str; + + switch (prop_id) { + case PROP_NUMBER: + g_free (priv->number); + priv->number = g_value_dup_string (value); + break; + case PROP_USERNAME: + g_free (priv->username); + priv->username = g_value_dup_string (value); + break; + case PROP_PASSWORD: + g_free (priv->password); + priv->password = g_value_dup_string (value); + break; + case PROP_APN: + g_free (priv->apn); + priv->apn = g_value_dup_string (value); + break; + case PROP_NETWORK_ID: + g_free (priv->network_id); + priv->network_id = g_value_dup_string (value); + break; + case PROP_NETWORK_TYPE: + priv->network_type = g_value_get_int (value); + break; + case PROP_BAND: + if (g_value_get_int (value) != -1) + g_warning ("Tried to set deprecated property " NM_SETTING_GSM_SETTING_NAME "/" NM_SETTING_GSM_BAND); + break; + case PROP_ALLOWED_BANDS: + priv->allowed_bands = g_value_get_uint (value); + break; + case PROP_PIN: + g_free (priv->pin); + priv->pin = g_value_dup_string (value); + break; + case PROP_PUK: + str = g_value_get_string (value); + if (str && strlen (str)) + g_warning ("Tried to set deprecated property " NM_SETTING_GSM_SETTING_NAME "/" NM_SETTING_GSM_PUK); + break; + case PROP_HOME_ONLY: + priv->home_only = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingGsm *setting = NM_SETTING_GSM (object); + + switch (prop_id) { + case PROP_NUMBER: + g_value_set_string (value, nm_setting_gsm_get_number (setting)); + break; + case PROP_USERNAME: + g_value_set_string (value, nm_setting_gsm_get_username (setting)); + break; + case PROP_PASSWORD: + g_value_set_string (value, nm_setting_gsm_get_password (setting)); + break; + case PROP_APN: + g_value_set_string (value, nm_setting_gsm_get_apn (setting)); + break; + case PROP_NETWORK_ID: + g_value_set_string (value, nm_setting_gsm_get_network_id (setting)); + break; + case PROP_NETWORK_TYPE: + g_value_set_int (value, nm_setting_gsm_get_network_type (setting)); + break; + case PROP_ALLOWED_BANDS: + g_value_set_uint (value, nm_setting_gsm_get_allowed_bands (setting)); + break; + case PROP_PIN: + g_value_set_string (value, nm_setting_gsm_get_pin (setting)); + break; + case PROP_PUK: + /* deprecated */ + g_value_set_string (value, NULL); + break; + case PROP_BAND: + /* deprecated */ + g_value_set_int (value, -1); + break; + case PROP_HOME_ONLY: + g_value_set_boolean (value, nm_setting_gsm_get_home_only (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_gsm_class_init (NMSettingGsmClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingGsmPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + parent_class->need_secrets = need_secrets; + + /* Properties */ + + /** + * NMSettingGsm:number: + * + * Number to dial when establishing a PPP data session with the GSM-based + * mobile broadband network. In most cases, leave the number blank and a + * number selecting the APN specified in the 'apn' property will be used + * automatically when required. + **/ + g_object_class_install_property + (object_class, PROP_NUMBER, + g_param_spec_string (NM_SETTING_GSM_NUMBER, + "Number", + "Number to dial when establishing a PPP data session " + "with the GSM-based mobile broadband network. In most " + "cases, leave the number blank and a number selecting " + "the APN specified in the 'apn' property will be used " + "automatically when required.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingGsm:username: + * + * The username used to authenticate with the network, if required. Many + * providers do not require a username, or accept any username. But if a + * username is required, it is specified here. + **/ + g_object_class_install_property + (object_class, PROP_USERNAME, + g_param_spec_string (NM_SETTING_GSM_USERNAME, + "Username", + "Username used to authenticate with the network, if " + "required. Note that many providers do not require " + "a username or accept any username.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingGsm:password: + * + * The password used to authenticate with the network, if required. Many + * providers do not require a password, or accept any password. But if a + * password is required, it is specified here. + **/ + g_object_class_install_property + (object_class, PROP_PASSWORD, + g_param_spec_string (NM_SETTING_GSM_PASSWORD, + "Password", + "Password used to authenticate with the network, if " + "required. Note that many providers do not require " + "a password or accept any password.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSettingGsm:apn: + * + * The GPRS Access Point Name specifying the APN used when establishing a + * data session with the GSM-based network. The APN often determines how + * the user will be billed for their network usage and whether the user has + * access to the Internet or just a provider-specific walled-garden, so it + * is important to use the correct APN for the user's mobile broadband plan. + **/ + g_object_class_install_property + (object_class, PROP_APN, + g_param_spec_string (NM_SETTING_GSM_APN, + "APN", + "The GPRS Access Point Name specifying the APN used " + "when establishing a data session with the GSM-based " + "network. The APN often determines how the user will " + "be billed for their network usage and whether the " + "user has access to the Internet or just a provider-" + "specific walled-garden, so it is important to use " + "the correct APN for the user's mobile broadband " + "plan.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingGsm:network-id: + * + * The Network ID (GSM LAI format, ie MCC-MNC) to force specific network + * registration. If the Network ID is specified, NetworkManager will + * attempt to force the device to register only on the specified network. + * This can be used to ensure that the device does not roam when direct + * roaming control of the device is not otherwise possible. + **/ + g_object_class_install_property + (object_class, PROP_NETWORK_ID, + g_param_spec_string (NM_SETTING_GSM_NETWORK_ID, + "Network ID", + "The Network ID (GSM LAI format, ie MCC-MNC) to force " + "specific network registration. If the Network ID is " + "specified, NetworkManager will attempt to force the " + "device to register only on the specified network. " + "This can be used to ensure that the device does not " + "roam when direct roaming control of the device is " + "not otherwise possible.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingGsm:network-type: + * + * Network preference to force the device to only use specific network + * technologies. The permitted values are: -1: any, 0: 3G only, + * 1: GPRS/EDGE only, 2: prefer 3G, and 3: prefer 2G. Note that not all + * devices allow network preference control. + **/ + g_object_class_install_property + (object_class, PROP_NETWORK_TYPE, + g_param_spec_int (NM_SETTING_GSM_NETWORK_TYPE, + "Network type", + "Network preference to force the device to only use " + "specific network technologies. The permitted values " + "are: -1: any, 0: 3G only, 1: GPRS/EDGE only, " + "2: prefer 3G, and 3: prefer 2G. Note that not all " + "devices allow network preference control.", + NM_SETTING_GSM_NETWORK_TYPE_ANY, + NM_SETTING_GSM_NETWORK_TYPE_PREFER_GPRS_EDGE, + NM_SETTING_GSM_NETWORK_TYPE_ANY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingGsm:allowed-bands: + * + * Bitfield of allowed frequency bands. Note that not all devices allow + * frequency band control. + **/ + g_object_class_install_property + (object_class, PROP_ALLOWED_BANDS, + g_param_spec_uint (NM_SETTING_GSM_ALLOWED_BANDS, + "Allowed Bands", + "Bitfield of allowed frequency bands. Note that " + "not all devices allow frequency band control.", + NM_SETTING_GSM_BAND_UNKNOWN, + NM_SETTING_GSM_BAND_UNKNOWN + || NM_SETTING_GSM_BAND_ANY + || NM_SETTING_GSM_BAND_EGSM + || NM_SETTING_GSM_BAND_DCS + || NM_SETTING_GSM_BAND_PCS + || NM_SETTING_GSM_BAND_G850 + || NM_SETTING_GSM_BAND_U2100 + || NM_SETTING_GSM_BAND_U1800 + || NM_SETTING_GSM_BAND_U17IV + || NM_SETTING_GSM_BAND_U800 + || NM_SETTING_GSM_BAND_U850 + || NM_SETTING_GSM_BAND_U900 + || NM_SETTING_GSM_BAND_U17IX + || NM_SETTING_GSM_BAND_U1900, + NM_SETTING_GSM_BAND_ANY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingGsm:pin: + * + * If the SIM is locked with a PIN it must be unlocked before any other + * operations are requested. Specify the PIN here to allow operation of + * the device. + **/ + g_object_class_install_property + (object_class, PROP_PIN, + g_param_spec_string (NM_SETTING_GSM_PIN, + "PIN", + "If the SIM is locked with a PIN it must be unlocked " + "before any other operations are requested. Specify " + "the PIN here to allow operation of the device.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSettingGsm:home-only: + * + * When TRUE, only connections to the home network will be allowed. + * Connections to roaming networks will not be made. + **/ + g_object_class_install_property + (object_class, PROP_HOME_ONLY, + g_param_spec_boolean (NM_SETTING_GSM_HOME_ONLY, + "PIN", + "When TRUE, only connections to the home network will " + "be allowed. Connections to roaming networks will " + "not be made.", + FALSE, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /* Deprecated properties */ + /** + * NMSettingGsm:puk: + * + * DEPRECATED + **/ + g_object_class_install_property + (object_class, PROP_PUK, + g_param_spec_string (NM_SETTING_GSM_PUK, + "PUK (DEPRECATED and UNUSED)", + "PUK (DEPRECATED and UNUSED)", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSettingGsm:band: + * + * DEPRECATED + **/ + g_object_class_install_property + (object_class, PROP_BAND, + g_param_spec_int (NM_SETTING_GSM_BAND, + "Band (DEPRECATED and UNUSED)", + "Band (DEPRECATED and UNUSED)", + -1, 5, -1, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); +} diff --git a/libnm-util/nm-setting-gsm.h b/libnm-util/nm-setting-gsm.h new file mode 100644 index 00000000..0ac71224 --- /dev/null +++ b/libnm-util/nm-setting-gsm.h @@ -0,0 +1,135 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2010 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_GSM_H +#define NM_SETTING_GSM_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_GSM (nm_setting_gsm_get_type ()) +#define NM_SETTING_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_GSM, NMSettingGsm)) +#define NM_SETTING_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_GSM, NMSettingGsmClass)) +#define NM_IS_SETTING_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_GSM)) +#define NM_IS_SETTING_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_GSM)) +#define NM_SETTING_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_GSM, NMSettingGsmClass)) + +#define NM_SETTING_GSM_SETTING_NAME "gsm" + +typedef enum +{ + NM_SETTING_GSM_ERROR_UNKNOWN = 0, + NM_SETTING_GSM_ERROR_INVALID_PROPERTY, + NM_SETTING_GSM_ERROR_MISSING_PROPERTY, + NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING +} NMSettingGsmError; + +#define NM_TYPE_SETTING_GSM_ERROR (nm_setting_gsm_error_get_type ()) +GType nm_setting_gsm_error_get_type (void); + +#define NM_SETTING_GSM_ERROR nm_setting_gsm_error_quark () +GQuark nm_setting_gsm_error_quark (void); + +#define NM_SETTING_GSM_NUMBER "number" +#define NM_SETTING_GSM_USERNAME "username" +#define NM_SETTING_GSM_PASSWORD "password" +#define NM_SETTING_GSM_APN "apn" +#define NM_SETTING_GSM_NETWORK_ID "network-id" +#define NM_SETTING_GSM_NETWORK_TYPE "network-type" +#define NM_SETTING_GSM_ALLOWED_BANDS "allowed-bands" +#define NM_SETTING_GSM_PIN "pin" +#define NM_SETTING_GSM_HOME_ONLY "home-only" + +/* DEPRECATED & UNUSED */ +#define NM_SETTING_GSM_PUK "puk" +#define NM_SETTING_GSM_BAND "band" + +/* DEPRECATED, use NM_SETTING_NETWORK_TYPE_* instead */ +#define NM_GSM_NETWORK_ANY NM_SETTING_GSM_NETWORK_TYPE_ANY +#define NM_GSM_NETWORK_UMTS_HSPA NM_SETTING_GSM_NETWORK_TYPE_UMTS_HSPA +#define NM_GSM_NETWORK_GPRS_EDGE NM_SETTING_GSM_NETWORK_TYPE_GPRS_EDGE +#define NM_GSM_NETWORK_PREFER_UMTS_HSPA NM_SETTING_GSM_NETWORK_TYPE_PREFER_UMTS_HSPA +#define NM_GSM_NETWORK_PREFER_GPRS_EDGE NM_SETTING_GSM_NETWORK_TYPE_PREFER_GPRS_EDGE + +typedef enum { + NM_SETTING_GSM_NETWORK_TYPE_ANY = -1, + NM_SETTING_GSM_NETWORK_TYPE_UMTS_HSPA = 0, + NM_SETTING_GSM_NETWORK_TYPE_GPRS_EDGE = 1, + NM_SETTING_GSM_NETWORK_TYPE_PREFER_UMTS_HSPA = 2, + NM_SETTING_GSM_NETWORK_TYPE_PREFER_GPRS_EDGE = 3 +} NMSettingGsmNetworkType; + +typedef enum { + NM_SETTING_GSM_BAND_UNKNOWN = 0x00000000, + NM_SETTING_GSM_BAND_ANY = 0x00000001, + NM_SETTING_GSM_BAND_EGSM = 0x00000002, /* 900 MHz */ + NM_SETTING_GSM_BAND_DCS = 0x00000004, /* 1800 MHz */ + NM_SETTING_GSM_BAND_PCS = 0x00000008, /* 1900 MHz */ + NM_SETTING_GSM_BAND_G850 = 0x00000010, /* 850 MHz */ + NM_SETTING_GSM_BAND_U2100 = 0x00000020, /* WCDMA 3GPP UMTS 2100 MHz (Class I) */ + NM_SETTING_GSM_BAND_U1800 = 0x00000040, /* WCDMA 3GPP UMTS 1800 MHz (Class III) */ + NM_SETTING_GSM_BAND_U17IV = 0x00000080, /* WCDMA 3GPP AWS 1700/2100 MHz (Class IV) */ + NM_SETTING_GSM_BAND_U800 = 0x00000100, /* WCDMA 3GPP UMTS 800 MHz (Class VI) */ + NM_SETTING_GSM_BAND_U850 = 0x00000200, /* WCDMA 3GPP UMTS 850 MHz (Class V) */ + NM_SETTING_GSM_BAND_U900 = 0x00000400, /* WCDMA 3GPP UMTS 900 MHz (Class VIII) */ + NM_SETTING_GSM_BAND_U17IX = 0x00000800, /* WCDMA 3GPP UMTS 1700 MHz (Class IX) */ + NM_SETTING_GSM_BAND_U1900 = 0x00001000, /* WCDMA 3GPP UMTS 1900 MHz (Class II) */ +} NMSettingGsmNetworkBand; + +typedef struct { + NMSetting parent; +} NMSettingGsm; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingGsmClass; + +GType nm_setting_gsm_get_type (void); + +NMSetting *nm_setting_gsm_new (void); +const char *nm_setting_gsm_get_number (NMSettingGsm *setting); +const char *nm_setting_gsm_get_username (NMSettingGsm *setting); +const char *nm_setting_gsm_get_password (NMSettingGsm *setting); +const char *nm_setting_gsm_get_apn (NMSettingGsm *setting); +const char *nm_setting_gsm_get_network_id (NMSettingGsm *setting); +int nm_setting_gsm_get_network_type (NMSettingGsm *setting); +guint32 nm_setting_gsm_get_allowed_bands (NMSettingGsm *setting); +const char *nm_setting_gsm_get_pin (NMSettingGsm *setting); +gboolean nm_setting_gsm_get_home_only (NMSettingGsm *setting); + +/* DEPRECATED & UNUSED */ +const char *nm_setting_gsm_get_puk (NMSettingGsm *setting); +int nm_setting_gsm_get_band (NMSettingGsm *setting); + +G_END_DECLS + +#endif /* NM_SETTING_GSM_H */ diff --git a/libnm-util/nm-setting-ip4-config.c b/libnm-util/nm-setting-ip4-config.c new file mode 100644 index 00000000..186e41e2 --- /dev/null +++ b/libnm-util/nm-setting-ip4-config.c @@ -0,0 +1,1287 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2010 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> + +#include <dbus/dbus-glib.h> +#include "nm-setting-ip4-config.h" +#include "nm-param-spec-specialized.h" +#include "nm-utils.h" +#include "nm-dbus-glib-types.h" + +GQuark +nm_setting_ip4_config_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-ip4-config-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_ip4_config_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_IP4_CONFIG_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_IP4_CONFIG_ERROR_MISSING_PROPERTY, "MissingProperty"), + /* The specified property was not allowed in combination with the current 'method' */ + ENUM_ENTRY (NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD, "NotAllowedForMethod"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingIP4ConfigError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING) + +#define NM_SETTING_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigPrivate)) + +typedef struct { + char *method; + GArray *dns; /* array of guint32; elements in network byte order */ + GSList *dns_search; /* list of strings */ + GSList *addresses; /* array of NMIP4Address */ + GSList *routes; /* array of NMIP4Route */ + gboolean ignore_auto_routes; + gboolean ignore_auto_dns; + char *dhcp_client_id; + gboolean dhcp_send_hostname; + char *dhcp_hostname; + gboolean never_default; + gboolean may_fail; +} NMSettingIP4ConfigPrivate; + +enum { + PROP_0, + PROP_METHOD, + PROP_DNS, + PROP_DNS_SEARCH, + PROP_ADDRESSES, + PROP_ROUTES, + PROP_IGNORE_AUTO_ROUTES, + PROP_IGNORE_AUTO_DNS, + PROP_DHCP_CLIENT_ID, + PROP_DHCP_SEND_HOSTNAME, + PROP_DHCP_HOSTNAME, + PROP_NEVER_DEFAULT, + PROP_MAY_FAIL, + + LAST_PROP +}; + +NMSetting * +nm_setting_ip4_config_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_IP4_CONFIG, NULL); +} + +const char * +nm_setting_ip4_config_get_method (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->method; +} + +guint32 +nm_setting_ip4_config_get_num_dns (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), 0); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dns->len; +} + +guint32 +nm_setting_ip4_config_get_dns (NMSettingIP4Config *setting, guint32 i) +{ + NMSettingIP4ConfigPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), 0); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + g_return_val_if_fail (i <= priv->dns->len, 0); + + return g_array_index (priv->dns, guint32, i); +} + +gboolean +nm_setting_ip4_config_add_dns (NMSettingIP4Config *setting, guint32 dns) +{ + NMSettingIP4ConfigPrivate *priv; + int i; + + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + for (i = 0; i < priv->dns->len; i++) { + if (dns == g_array_index (priv->dns, guint32, i)) + return FALSE; + } + + g_array_append_val (priv->dns, dns); + return TRUE; +} + +void +nm_setting_ip4_config_remove_dns (NMSettingIP4Config *setting, guint32 i) +{ + NMSettingIP4ConfigPrivate *priv; + + g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting)); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + g_return_if_fail (i <= priv->dns->len); + + g_array_remove_index (priv->dns, i); +} + +void +nm_setting_ip4_config_clear_dns (NMSettingIP4Config *setting) +{ + NMSettingIP4ConfigPrivate *priv; + + g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting)); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + g_array_remove_range (priv->dns, 0, priv->dns->len); +} + +guint32 +nm_setting_ip4_config_get_num_dns_searches (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), 0); + + return g_slist_length (NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dns_search); +} + +const char * +nm_setting_ip4_config_get_dns_search (NMSettingIP4Config *setting, guint32 i) +{ + NMSettingIP4ConfigPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->dns_search), NULL); + + return (const char *) g_slist_nth_data (priv->dns_search, i); +} + +gboolean +nm_setting_ip4_config_add_dns_search (NMSettingIP4Config *setting, + const char *dns_search) +{ + NMSettingIP4ConfigPrivate *priv; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + g_return_val_if_fail (dns_search != NULL, FALSE); + g_return_val_if_fail (dns_search[0] != '\0', FALSE); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + for (iter = priv->dns_search; iter; iter = g_slist_next (iter)) { + if (!strcmp (dns_search, (char *) iter->data)) + return FALSE; + } + + priv->dns_search = g_slist_append (priv->dns_search, g_strdup (dns_search)); + return TRUE; +} + +void +nm_setting_ip4_config_remove_dns_search (NMSettingIP4Config *setting, guint32 i) +{ + NMSettingIP4ConfigPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting)); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + elt = g_slist_nth (priv->dns_search, i); + g_return_if_fail (elt != NULL); + + g_free (elt->data); + priv->dns_search = g_slist_delete_link (priv->dns_search, elt); +} + +void +nm_setting_ip4_config_clear_dns_searches (NMSettingIP4Config *setting) +{ + g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting)); + + nm_utils_slist_free (NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dns_search, g_free); + NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dns_search = NULL; +} + +guint32 +nm_setting_ip4_config_get_num_addresses (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), 0); + + return g_slist_length (NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->addresses); +} + +NMIP4Address * +nm_setting_ip4_config_get_address (NMSettingIP4Config *setting, guint32 i) +{ + NMSettingIP4ConfigPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->addresses), NULL); + + return (NMIP4Address *) g_slist_nth_data (priv->addresses, i); +} + +gboolean +nm_setting_ip4_config_add_address (NMSettingIP4Config *setting, + NMIP4Address *address) +{ + NMSettingIP4ConfigPrivate *priv; + NMIP4Address *copy; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + g_return_val_if_fail (address != NULL, FALSE); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + for (iter = priv->addresses; iter; iter = g_slist_next (iter)) { + if (nm_ip4_address_compare ((NMIP4Address *) iter->data, address)) + return FALSE; + } + + copy = nm_ip4_address_dup (address); + g_return_val_if_fail (copy != NULL, FALSE); + + priv->addresses = g_slist_append (priv->addresses, copy); + return TRUE; +} + +void +nm_setting_ip4_config_remove_address (NMSettingIP4Config *setting, guint32 i) +{ + NMSettingIP4ConfigPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting)); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + elt = g_slist_nth (priv->addresses, i); + g_return_if_fail (elt != NULL); + + nm_ip4_address_unref ((NMIP4Address *) elt->data); + priv->addresses = g_slist_delete_link (priv->addresses, elt); +} + +void +nm_setting_ip4_config_clear_addresses (NMSettingIP4Config *setting) +{ + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + + g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting)); + + nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip4_address_unref); + priv->addresses = NULL; +} + +guint32 +nm_setting_ip4_config_get_num_routes (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), 0); + + return g_slist_length (NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->routes); +} + +NMIP4Route * +nm_setting_ip4_config_get_route (NMSettingIP4Config *setting, guint32 i) +{ + NMSettingIP4ConfigPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->routes), NULL); + + return (NMIP4Route *) g_slist_nth_data (priv->routes, i); +} + +gboolean +nm_setting_ip4_config_add_route (NMSettingIP4Config *setting, + NMIP4Route *route) +{ + NMSettingIP4ConfigPrivate *priv; + NMIP4Route *copy; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + g_return_val_if_fail (route != NULL, FALSE); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + for (iter = priv->routes; iter; iter = g_slist_next (iter)) { + if (nm_ip4_route_compare ((NMIP4Route *) iter->data, route)) + return FALSE; + } + + copy = nm_ip4_route_dup (route); + g_return_val_if_fail (copy != NULL, FALSE); + + priv->routes = g_slist_append (priv->routes, copy); + return TRUE; +} + +void +nm_setting_ip4_config_remove_route (NMSettingIP4Config *setting, guint32 i) +{ + NMSettingIP4ConfigPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting)); + + priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + elt = g_slist_nth (priv->routes, i); + g_return_if_fail (elt != NULL); + + nm_ip4_route_unref ((NMIP4Route *) elt->data); + priv->routes = g_slist_delete_link (priv->routes, elt); +} + +void +nm_setting_ip4_config_clear_routes (NMSettingIP4Config *setting) +{ + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + + g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting)); + + nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip4_route_unref); + priv->routes = NULL; +} + +gboolean +nm_setting_ip4_config_get_ignore_auto_routes (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->ignore_auto_routes; +} + +gboolean +nm_setting_ip4_config_get_ignore_auto_dns (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->ignore_auto_dns; +} + +const char * +nm_setting_ip4_config_get_dhcp_client_id (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_client_id; +} + +gboolean +nm_setting_ip4_config_get_dhcp_send_hostname (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_send_hostname; +} + +const char * +nm_setting_ip4_config_get_dhcp_hostname (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_hostname; +} + +gboolean +nm_setting_ip4_config_get_never_default (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->never_default; +} + +gboolean +nm_setting_ip4_config_get_may_fail (NMSettingIP4Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE); + + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->may_fail; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + GSList *iter; + int i; + + if (!priv->method) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_MISSING_PROPERTY, + NM_SETTING_IP4_CONFIG_METHOD); + return FALSE; + } + + if (!strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { + if (!priv->addresses) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_MISSING_PROPERTY, + NM_SETTING_IP4_CONFIG_ADDRESSES); + return FALSE; + } + } else if ( !strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) + || !strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) + || !strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { + if (priv->dns && priv->dns->len) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD, + NM_SETTING_IP4_CONFIG_DNS); + return FALSE; + } + + if (g_slist_length (priv->dns_search)) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD, + NM_SETTING_IP4_CONFIG_DNS_SEARCH); + return FALSE; + } + + if (g_slist_length (priv->addresses)) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD, + NM_SETTING_IP4_CONFIG_ADDRESSES); + return FALSE; + } + } else if (!strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + /* nothing to do */ + } else { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, + NM_SETTING_IP4_CONFIG_METHOD); + return FALSE; + } + + if (priv->dhcp_client_id && !strlen (priv->dhcp_client_id)) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, + NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID); + return FALSE; + } + + if (priv->dhcp_hostname && !strlen (priv->dhcp_hostname)) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, + NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME); + return FALSE; + } + + /* Validate addresses */ + for (iter = priv->addresses, i = 0; iter; iter = g_slist_next (iter), i++) { + NMIP4Address *addr = (NMIP4Address *) iter->data; + guint32 prefix = nm_ip4_address_get_prefix (addr); + + if (!nm_ip4_address_get_address (addr)) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, + NM_SETTING_IP4_CONFIG_ADDRESSES); + return FALSE; + } + + if (!prefix || prefix > 32) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, + NM_SETTING_IP4_CONFIG_ADDRESSES); + return FALSE; + } + } + + /* Validate routes */ + for (iter = priv->routes, i = 0; iter; iter = g_slist_next (iter), i++) { + NMIP4Route *route = (NMIP4Route *) iter->data; + guint32 prefix = nm_ip4_route_get_prefix (route); + + if (!nm_ip4_route_get_dest (route)) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, + NM_SETTING_IP4_CONFIG_ROUTES); + return FALSE; + } + + if (!prefix || prefix > 32) { + g_set_error (error, + NM_SETTING_IP4_CONFIG_ERROR, + NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, + NM_SETTING_IP4_CONFIG_ROUTES); + return FALSE; + } + } + + return TRUE; +} + + +static void +nm_setting_ip4_config_init (NMSettingIP4Config *setting) +{ + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_IP4_CONFIG_SETTING_NAME, NULL); + + priv->dns = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3); +} + +static void +finalize (GObject *object) +{ + NMSettingIP4Config *self = NM_SETTING_IP4_CONFIG (object); + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (self); + + g_free (priv->method); + + g_array_free (priv->dns, TRUE); + + nm_utils_slist_free (priv->dns_search, g_free); + nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip4_address_unref); + nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip4_route_unref); + + G_OBJECT_CLASS (nm_setting_ip4_config_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingIP4Config *setting = NM_SETTING_IP4_CONFIG (object); + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_METHOD: + g_free (priv->method); + priv->method = g_value_dup_string (value); + break; + case PROP_DNS: + g_array_free (priv->dns, TRUE); + priv->dns = g_value_dup_boxed (value); + if (!priv->dns) + priv->dns = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3); + break; + case PROP_DNS_SEARCH: + nm_utils_slist_free (priv->dns_search, g_free); + priv->dns_search = g_value_dup_boxed (value); + break; + case PROP_ADDRESSES: + nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip4_address_unref); + priv->addresses = nm_utils_ip4_addresses_from_gvalue (value); + break; + case PROP_ROUTES: + nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip4_route_unref); + priv->routes = nm_utils_ip4_routes_from_gvalue (value); + break; + case PROP_IGNORE_AUTO_ROUTES: + priv->ignore_auto_routes = g_value_get_boolean (value); + break; + case PROP_IGNORE_AUTO_DNS: + priv->ignore_auto_dns = g_value_get_boolean (value); + break; + case PROP_DHCP_CLIENT_ID: + g_free (priv->dhcp_client_id); + priv->dhcp_client_id = g_value_dup_string (value); + break; + case PROP_DHCP_SEND_HOSTNAME: + priv->dhcp_send_hostname = g_value_get_boolean (value); + break; + case PROP_DHCP_HOSTNAME: + g_free (priv->dhcp_hostname); + priv->dhcp_hostname = g_value_dup_string (value); + /* FIXME: Is this a good idea? */ + if (priv->dhcp_hostname) + priv->dhcp_send_hostname = TRUE; + break; + case PROP_NEVER_DEFAULT: + priv->never_default = g_value_get_boolean (value); + break; + case PROP_MAY_FAIL: + priv->may_fail = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingIP4Config *setting = NM_SETTING_IP4_CONFIG (object); + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_METHOD: + g_value_set_string (value, nm_setting_ip4_config_get_method (setting)); + break; + case PROP_DNS: + g_value_set_boxed (value, priv->dns); + break; + case PROP_DNS_SEARCH: + g_value_set_boxed (value, priv->dns_search); + break; + case PROP_ADDRESSES: + nm_utils_ip4_addresses_to_gvalue (priv->addresses, value); + break; + case PROP_ROUTES: + nm_utils_ip4_routes_to_gvalue (priv->routes, value); + break; + case PROP_IGNORE_AUTO_ROUTES: + g_value_set_boolean (value, nm_setting_ip4_config_get_ignore_auto_routes (setting)); + break; + case PROP_IGNORE_AUTO_DNS: + g_value_set_boolean (value, nm_setting_ip4_config_get_ignore_auto_dns (setting)); + break; + case PROP_DHCP_CLIENT_ID: + g_value_set_string (value, nm_setting_ip4_config_get_dhcp_client_id (setting)); + break; + case PROP_DHCP_SEND_HOSTNAME: + g_value_set_boolean (value, nm_setting_ip4_config_get_dhcp_send_hostname (setting)); + break; + case PROP_DHCP_HOSTNAME: + g_value_set_string (value, nm_setting_ip4_config_get_dhcp_hostname (setting)); + break; + case PROP_NEVER_DEFAULT: + g_value_set_boolean (value, priv->never_default); + break; + case PROP_MAY_FAIL: + g_value_set_boolean (value, priv->may_fail); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingIP4ConfigPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ + /** + * NMSettingIP4Config:method: + * + * IPv4 configuration method. If 'auto' is specified then the appropriate + * automatic method (DHCP, PPP, etc) is used for the interface and most + * other properties can be left unset. If 'link-local' is specified, then a + * link-local address in the 169.254/16 range will be assigned to the + * interface. If 'manual' is specified, static IP addressing is used and at + * least one IP address must be given in the 'addresses' property. If + * 'shared' is specified (indicating that this connection will provide + * network access to other computers) then the interface is assigned an + * address in the 10.42.x.1/24 range and a DHCP and forwarding DNS server + * are started, and the interface is NAT-ed to the current default network + * connection. 'disabled' means IPv4 will not be used on this connection. + * This property must be set. + **/ + g_object_class_install_property + (object_class, PROP_METHOD, + g_param_spec_string (NM_SETTING_IP4_CONFIG_METHOD, + "Method", + "IPv4 configuration method. If 'auto' is specified " + "then the appropriate automatic method (DHCP, PPP, " + "etc) is used for the interface and most other " + "properties can be left unset. If 'link-local' " + "is specified, then a link-local address in the " + "169.254/16 range will be assigned to the " + "interface. If 'manual' is specified, static IP " + "addressing is used and at least one IP address " + "must be given in the 'addresses' property. If " + "'shared' is specified (indicating that this " + "connection will provide network access to other " + "computers) then the interface is assigned an " + "address in the 10.42.x.1/24 range and a DHCP and " + "forwarding DNS server are started, and the " + "interface is NAT-ed to the current default network " + "connection. 'disabled' means IPv4 will not be " + "used on this connection. This property must be set.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:dns: + * + * List of DNS servers (network byte order). For the 'auto' method, these + * DNS servers are appended to those (if any) returned by automatic + * configuration. DNS servers cannot be used with the 'shared', 'link-local', + * or 'disabled' methods as there is no usptream network. In all other + * methods, these DNS servers are used as the only DNS servers for this + * connection. + **/ + g_object_class_install_property + (object_class, PROP_DNS, + _nm_param_spec_specialized (NM_SETTING_IP4_CONFIG_DNS, + "DNS", + "List of DNS servers (network byte order). For " + "the 'auto' method, these DNS servers are " + "appended to those (if any) returned by automatic " + "configuration. DNS servers cannot be used with " + "the 'shared', 'link-local', or 'disabled' " + "methods as there is no usptream network. In all " + "other methods, these DNS servers are used as the " + "only DNS servers for this connection.", + DBUS_TYPE_G_UINT_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:dns-search: + * + * List of DNS search domains. For the 'auto' method, these search domains + * are appended to those returned by automatic configuration. Search domains + * cannot be used with the 'shared', 'link-local', or 'disabled' methods as + * there is no upstream network. In all other methods, these search domains + * are used as the only search domains for this connection. + **/ + g_object_class_install_property + (object_class, PROP_DNS_SEARCH, + _nm_param_spec_specialized (NM_SETTING_IP4_CONFIG_DNS_SEARCH, + "DNS search", + "List of DNS search domains. For the 'auto' " + "method, these search domains are appended to " + "those returned by automatic configuration. " + "Search domains cannot be used with the 'shared', " + "'link-local', or 'disabled' methods as there is " + "no upstream network. In all other methods, these " + "search domains are used as the only search domains " + "for this connection.", + DBUS_TYPE_G_LIST_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:addresses: + * + * Array of IPv4 address structures. Each IPv4 address structure is + * composed of 3 32-bit values; the first being the IPv4 address (network + * byte order), the second the prefix (1 - 32), and last the IPv4 gateway + * (network byte order). The gateway may be left as 0 if no gateway exists + * for that subnet. For the 'auto' method, given IP addresses are appended + * to those returned by automatic configuration. Addresses cannot be used + * with the 'shared', 'link-local', or 'disabled' methods as addressing is + * either automatic or disabled with these methods. + **/ + g_object_class_install_property + (object_class, PROP_ADDRESSES, + _nm_param_spec_specialized (NM_SETTING_IP4_CONFIG_ADDRESSES, + "Addresses", + "Array of IPv4 address structures. Each IPv4 " + "address structure is composed of 3 32-bit values; " + "the first being the IPv4 address (network byte " + "order), the second the prefix (1 - 32), and " + "last the IPv4 gateway (network byte order). The " + "gateway may be left as 0 if no gateway exists " + "for that subnet. For the 'auto' method, given " + "IP addresses are appended to those returned by " + "automatic configuration. Addresses cannot be " + "used with the 'shared', 'link-local', or " + "'disabled' methods as addressing is either " + "automatic or disabled with these methods.", + DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:routes: + * + * Array of IPv4 route structures. Each IPv4 route structure is composed + * of 4 32-bit values; the first being the destination IPv4 network or + * address (network byte order), the second the destination network or + * address prefix (1 - 32), the third being the next-hop (network byte + * order) if any, and the fourth being the route metric. For the 'auto' + * method, given IP routes are appended to those returned by automatic + * configuration. Routes cannot be used with the 'shared', 'link-local', + * or 'disabled' methods because there is no upstream network. + **/ + g_object_class_install_property + (object_class, PROP_ROUTES, + _nm_param_spec_specialized (NM_SETTING_IP4_CONFIG_ROUTES, + "Routes", + "Array of IPv4 route structures. Each IPv4 route " + "structure is composed of 4 32-bit values; the " + "first being the destination IPv4 network or " + "address (network byte order), the second the " + "destination network or address prefix (1 - 32), " + "the third being the next-hop (network byte order) " + "if any, and the fourth being the route metric. " + "For the 'auto' method, given IP routes are " + "appended to those returned by automatic " + "configuration. Routes cannot be used with the " + "'shared', 'link-local', or 'disabled', methods " + "as there is no upstream network.", + DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:ignore-auto-routes: + * + * When the method is set to 'auto' and this property to TRUE, automatically + * configured routes are ignored and only routes specified in + * #NMSettingIP4Config:routes, if any, are used. + **/ + g_object_class_install_property + (object_class, PROP_IGNORE_AUTO_ROUTES, + g_param_spec_boolean (NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, + "Ignore automatic routes", + "When the method is set to 'auto' and this property " + "to TRUE, automatically configured routes are " + "ignored and only routes specified in the 'routes' " + "property, if any, are used.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:ignore-auto-dns: + * + * When the method is set to 'auto' and this property to TRUE, automatically + * configured nameservers and search domains are ignored and only nameservers + * and search domains specified in #NMSettingIP4Config:dns and + * #NMSettingIP4Config:dns-search, if any, are used. + **/ + g_object_class_install_property + (object_class, PROP_IGNORE_AUTO_DNS, + g_param_spec_boolean (NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, + "Ignore automatic DNS", + "When the method is set to 'auto' and this property " + "to TRUE, automatically configured nameservers and " + "search domains are ignored and only nameservers and " + "search domains specified in the 'dns' and 'dns-search' " + "properties, if any, are used.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:dhcp-client-id: + * + * A string sent to the DHCP server to identify the local machine which the + * DHCP server may use to cusomize the DHCP lease and options. + **/ + g_object_class_install_property + (object_class, PROP_DHCP_CLIENT_ID, + g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, + "DHCP Client ID", + "A string sent to the DHCP server to identify the " + "local machine which the DHCP server may use to " + "cusomize the DHCP lease and options.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:dhcp-send-hostname: + * + * If TRUE, a hostname is sent to the DHCP server when acquiring a lease. + * Some DHCP servers use this hostname to update DNS databases, essentially + * providing a static hostname for the computer. If + * #NMSettingIP4Config:dhcp-hostname is empty and this property is TRUE, + * the current persistent hostname of the computer is sent. + **/ + g_object_class_install_property + (object_class, PROP_DHCP_SEND_HOSTNAME, + g_param_spec_boolean (NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME, + "Send DHCP hostname", + "If TRUE, a hostname is sent to the DHCP server when " + "acquiring a lease. Some DHCP servers use this " + "hostname to update DNS databases, essentially " + "providing a static hostname for the computer. If " + "the 'dhcp-hostname' property is empty and this " + "property is TRUE, the current persistent hostname " + "of the computer is sent.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:dhcp-hostname: + * + * If the #NMSettingIP4Config:dhcp-send-hostname property is TRUE, then the + * specified name will be sent to the DHCP server when acquiring a lease. + **/ + g_object_class_install_property + (object_class, PROP_DHCP_HOSTNAME, + g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, + "DHCP Hostname", + "If the 'dhcp-send-hostname' property is TRUE, then " + "the specified name will be sent to the DHCP server " + "when acquiring a lease.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:never-default: + * + * If TRUE, this connection will never be the default IPv4 connection, + * meaning it will never be assigned the default route by NetworkManager. + **/ + g_object_class_install_property + (object_class, PROP_NEVER_DEFAULT, + g_param_spec_boolean (NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, + "Never default", + "If TRUE, this connection will never be the default " + "IPv4 connection, meaning it will never be assigned " + "the default route by NetworkManager.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP4Config:may-fail: + * + * If TRUE, allow overall network configuration to proceed even if IPv4 + * configuration times out. Note that at least one IP configuration + * must succeed or overall network configuration will still fail. For + * example, in IPv6-only networks, setting this property to TRUE allows + * the overall network configuration to succeed if IPv4 configuration fails + * but IPv6 configuration completes successfully. + **/ + g_object_class_install_property + (object_class, PROP_MAY_FAIL, + g_param_spec_boolean (NM_SETTING_IP4_CONFIG_MAY_FAIL, + "May Fail", + "If TRUE, allow overall network configuration to " + "proceed even if IPv4 configuration times out. " + "Note that at least one IP configuration must " + "succeed or overall network configuration will still " + "fail. For example, in IPv6-only networks, setting " + "this property to TRUE allows the overall network " + "configuration to succeed if IPv4 configuration " + "fails but IPv6 configuration completes successfully.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); +} + + +struct NMIP4Address { + guint32 refcount; + guint32 address; /* network byte order */ + guint32 prefix; + guint32 gateway; /* network byte order */ +}; + +NMIP4Address * +nm_ip4_address_new (void) +{ + NMIP4Address *address; + + address = g_malloc0 (sizeof (NMIP4Address)); + address->refcount = 1; + return address; +} + +NMIP4Address * +nm_ip4_address_dup (NMIP4Address *source) +{ + NMIP4Address *address; + + g_return_val_if_fail (source != NULL, NULL); + g_return_val_if_fail (source->refcount > 0, NULL); + + address = nm_ip4_address_new (); + address->address = source->address; + address->prefix = source->prefix; + address->gateway = source->gateway; + + return address; +} + +void +nm_ip4_address_ref (NMIP4Address *address) +{ + g_return_if_fail (address != NULL); + g_return_if_fail (address->refcount > 0); + + address->refcount++; +} + +void +nm_ip4_address_unref (NMIP4Address *address) +{ + g_return_if_fail (address != NULL); + g_return_if_fail (address->refcount > 0); + + address->refcount--; + if (address->refcount == 0) { + memset (address, 0, sizeof (NMIP4Address)); + g_free (address); + } +} + +gboolean +nm_ip4_address_compare (NMIP4Address *address, NMIP4Address *other) +{ + g_return_val_if_fail (address != NULL, FALSE); + g_return_val_if_fail (address->refcount > 0, FALSE); + + g_return_val_if_fail (other != NULL, FALSE); + g_return_val_if_fail (other->refcount > 0, FALSE); + + if ( address->address != other->address + || address->prefix != other->prefix + || address->gateway != other->gateway) + return FALSE; + return TRUE; +} + +guint32 +nm_ip4_address_get_address (NMIP4Address *address) +{ + g_return_val_if_fail (address != NULL, 0); + g_return_val_if_fail (address->refcount > 0, 0); + + return address->address; +} + +void +nm_ip4_address_set_address (NMIP4Address *address, guint32 addr) +{ + g_return_if_fail (address != NULL); + g_return_if_fail (address->refcount > 0); + + address->address = addr; +} + +guint32 +nm_ip4_address_get_prefix (NMIP4Address *address) +{ + g_return_val_if_fail (address != NULL, 0); + g_return_val_if_fail (address->refcount > 0, 0); + + return address->prefix; +} + +void +nm_ip4_address_set_prefix (NMIP4Address *address, guint32 prefix) +{ + g_return_if_fail (address != NULL); + g_return_if_fail (address->refcount > 0); + + address->prefix = prefix; +} + +guint32 +nm_ip4_address_get_gateway (NMIP4Address *address) +{ + g_return_val_if_fail (address != NULL, 0); + g_return_val_if_fail (address->refcount > 0, 0); + + return address->gateway; +} + +void +nm_ip4_address_set_gateway (NMIP4Address *address, guint32 gateway) +{ + g_return_if_fail (address != NULL); + g_return_if_fail (address->refcount > 0); + + address->gateway = gateway; +} + + +struct NMIP4Route { + guint32 refcount; + + guint32 dest; /* network byte order */ + guint32 prefix; + guint32 next_hop; /* network byte order */ + guint32 metric; /* lower metric == more preferred */ +}; + +NMIP4Route * +nm_ip4_route_new (void) +{ + NMIP4Route *route; + + route = g_malloc0 (sizeof (NMIP4Route)); + route->refcount = 1; + return route; +} + +NMIP4Route * +nm_ip4_route_dup (NMIP4Route *source) +{ + NMIP4Route *route; + + g_return_val_if_fail (source != NULL, NULL); + g_return_val_if_fail (source->refcount > 0, NULL); + + route = nm_ip4_route_new (); + route->dest = source->dest; + route->prefix = source->prefix; + route->next_hop = source->next_hop; + route->metric = source->metric; + + return route; +} + +void +nm_ip4_route_ref (NMIP4Route *route) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + + route->refcount++; +} + +void +nm_ip4_route_unref (NMIP4Route *route) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + + route->refcount--; + if (route->refcount == 0) { + memset (route, 0, sizeof (NMIP4Route)); + g_free (route); + } +} + +gboolean +nm_ip4_route_compare (NMIP4Route *route, NMIP4Route *other) +{ + g_return_val_if_fail (route != NULL, FALSE); + g_return_val_if_fail (route->refcount > 0, FALSE); + + g_return_val_if_fail (other != NULL, FALSE); + g_return_val_if_fail (other->refcount > 0, FALSE); + + if ( route->dest != other->dest + || route->prefix != other->prefix + || route->next_hop != other->next_hop + || route->metric != other->metric) + return FALSE; + return TRUE; +} + +guint32 +nm_ip4_route_get_dest (NMIP4Route *route) +{ + g_return_val_if_fail (route != NULL, 0); + g_return_val_if_fail (route->refcount > 0, 0); + + return route->dest; +} + +void +nm_ip4_route_set_dest (NMIP4Route *route, guint32 dest) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + + route->dest = dest; +} + +guint32 +nm_ip4_route_get_prefix (NMIP4Route *route) +{ + g_return_val_if_fail (route != NULL, 0); + g_return_val_if_fail (route->refcount > 0, 0); + + return route->prefix; +} + +void +nm_ip4_route_set_prefix (NMIP4Route *route, guint32 prefix) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + + route->prefix = prefix; +} + +guint32 +nm_ip4_route_get_next_hop (NMIP4Route *route) +{ + g_return_val_if_fail (route != NULL, 0); + g_return_val_if_fail (route->refcount > 0, 0); + + return route->next_hop; +} + +void +nm_ip4_route_set_next_hop (NMIP4Route *route, guint32 next_hop) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + + route->next_hop = next_hop; +} + +guint32 +nm_ip4_route_get_metric (NMIP4Route *route) +{ + g_return_val_if_fail (route != NULL, 0); + g_return_val_if_fail (route->refcount > 0, 0); + + return route->metric; +} + +void +nm_ip4_route_set_metric (NMIP4Route *route, guint32 metric) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + + route->metric = metric; +} + diff --git a/libnm-util/nm-setting-ip4-config.h b/libnm-util/nm-setting-ip4-config.h new file mode 100644 index 00000000..80ddd475 --- /dev/null +++ b/libnm-util/nm-setting-ip4-config.h @@ -0,0 +1,177 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2010 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_IP4_CONFIG_H +#define NM_SETTING_IP4_CONFIG_H + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_IP4_CONFIG (nm_setting_ip4_config_get_type ()) +#define NM_SETTING_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4Config)) +#define NM_SETTING_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_IP4CONFIG, NMSettingIP4ConfigClass)) +#define NM_IS_SETTING_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_IP4_CONFIG)) +#define NM_IS_SETTING_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_IP4_CONFIG)) +#define NM_SETTING_IP4_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigClass)) + +#define NM_SETTING_IP4_CONFIG_SETTING_NAME "ipv4" + +typedef enum +{ + NM_SETTING_IP4_CONFIG_ERROR_UNKNOWN = 0, + NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY, + NM_SETTING_IP4_CONFIG_ERROR_MISSING_PROPERTY, + NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD +} NMSettingIP4ConfigError; + +#define NM_TYPE_SETTING_IP4_CONFIG_ERROR (nm_setting_ip4_config_error_get_type ()) +GType nm_setting_ip4_config_error_get_type (void); + +#define NM_SETTING_IP4_CONFIG_ERROR nm_setting_ip4_config_error_quark () +GQuark nm_setting_ip4_config_error_quark (void); + +#define NM_SETTING_IP4_CONFIG_METHOD "method" +#define NM_SETTING_IP4_CONFIG_DNS "dns" +#define NM_SETTING_IP4_CONFIG_DNS_SEARCH "dns-search" +#define NM_SETTING_IP4_CONFIG_ADDRESSES "addresses" +#define NM_SETTING_IP4_CONFIG_ROUTES "routes" +#define NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes" +#define NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns" +#define NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID "dhcp-client-id" +#define NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME "dhcp-send-hostname" +#define NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME "dhcp-hostname" +#define NM_SETTING_IP4_CONFIG_NEVER_DEFAULT "never-default" +#define NM_SETTING_IP4_CONFIG_MAY_FAIL "may-fail" + +#define NM_SETTING_IP4_CONFIG_METHOD_AUTO "auto" +#define NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL "link-local" +#define NM_SETTING_IP4_CONFIG_METHOD_MANUAL "manual" +#define NM_SETTING_IP4_CONFIG_METHOD_SHARED "shared" +#define NM_SETTING_IP4_CONFIG_METHOD_DISABLED "disabled" + +typedef struct NMIP4Address NMIP4Address; + +NMIP4Address * nm_ip4_address_new (void); +NMIP4Address * nm_ip4_address_dup (NMIP4Address *source); +void nm_ip4_address_ref (NMIP4Address *address); +void nm_ip4_address_unref (NMIP4Address *address); +/* Return TRUE if addresses are identical */ +gboolean nm_ip4_address_compare (NMIP4Address *address, NMIP4Address *other); + +guint32 nm_ip4_address_get_address (NMIP4Address *address); +void nm_ip4_address_set_address (NMIP4Address *address, + guint32 addr); /* network byte order */ + +guint32 nm_ip4_address_get_prefix (NMIP4Address *address); +void nm_ip4_address_set_prefix (NMIP4Address *address, + guint32 prefix); + +guint32 nm_ip4_address_get_gateway (NMIP4Address *address); +void nm_ip4_address_set_gateway (NMIP4Address *address, + guint32 gateway); /* network byte order */ + +typedef struct NMIP4Route NMIP4Route; + +NMIP4Route * nm_ip4_route_new (void); +NMIP4Route * nm_ip4_route_dup (NMIP4Route *route); +void nm_ip4_route_ref (NMIP4Route *route); +void nm_ip4_route_unref (NMIP4Route *route); +/* Return TRUE if routes are identical */ +gboolean nm_ip4_route_compare (NMIP4Route *route, NMIP4Route *other); + +guint32 nm_ip4_route_get_dest (NMIP4Route *route); +void nm_ip4_route_set_dest (NMIP4Route *route, + guint32 dest); /* network byte order */ + +guint32 nm_ip4_route_get_prefix (NMIP4Route *route); +void nm_ip4_route_set_prefix (NMIP4Route *route, + guint32 prefix); + +guint32 nm_ip4_route_get_next_hop (NMIP4Route *route); +void nm_ip4_route_set_next_hop (NMIP4Route *route, + guint32 next_hop); /* network byte order */ + +guint32 nm_ip4_route_get_metric (NMIP4Route *route); +void nm_ip4_route_set_metric (NMIP4Route *route, + guint32 metric); + + +typedef struct { + NMSetting parent; +} NMSettingIP4Config; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingIP4ConfigClass; + +GType nm_setting_ip4_config_get_type (void); + +NMSetting * nm_setting_ip4_config_new (void); +const char * nm_setting_ip4_config_get_method (NMSettingIP4Config *setting); + +guint32 nm_setting_ip4_config_get_num_dns (NMSettingIP4Config *setting); +guint32 nm_setting_ip4_config_get_dns (NMSettingIP4Config *setting, guint32 i); +gboolean nm_setting_ip4_config_add_dns (NMSettingIP4Config *setting, guint32 dns); +void nm_setting_ip4_config_remove_dns (NMSettingIP4Config *setting, guint32 i); +void nm_setting_ip4_config_clear_dns (NMSettingIP4Config *setting); + +guint32 nm_setting_ip4_config_get_num_dns_searches (NMSettingIP4Config *setting); +const char * nm_setting_ip4_config_get_dns_search (NMSettingIP4Config *setting, guint32 i); +gboolean nm_setting_ip4_config_add_dns_search (NMSettingIP4Config *setting, const char *dns_search); +void nm_setting_ip4_config_remove_dns_search (NMSettingIP4Config *setting, guint32 i); +void nm_setting_ip4_config_clear_dns_searches (NMSettingIP4Config *setting); + +guint32 nm_setting_ip4_config_get_num_addresses (NMSettingIP4Config *setting); +NMIP4Address *nm_setting_ip4_config_get_address (NMSettingIP4Config *setting, guint32 i); +gboolean nm_setting_ip4_config_add_address (NMSettingIP4Config *setting, NMIP4Address *address); +void nm_setting_ip4_config_remove_address (NMSettingIP4Config *setting, guint32 i); +void nm_setting_ip4_config_clear_addresses (NMSettingIP4Config *setting); + +guint32 nm_setting_ip4_config_get_num_routes (NMSettingIP4Config *setting); +NMIP4Route * nm_setting_ip4_config_get_route (NMSettingIP4Config *setting, guint32 i); +gboolean nm_setting_ip4_config_add_route (NMSettingIP4Config *setting, NMIP4Route *route); +void nm_setting_ip4_config_remove_route (NMSettingIP4Config *setting, guint32 i); +void nm_setting_ip4_config_clear_routes (NMSettingIP4Config *setting); + +gboolean nm_setting_ip4_config_get_ignore_auto_routes (NMSettingIP4Config *setting); +gboolean nm_setting_ip4_config_get_ignore_auto_dns (NMSettingIP4Config *setting); +const char * nm_setting_ip4_config_get_dhcp_client_id (NMSettingIP4Config *setting); +gboolean nm_setting_ip4_config_get_dhcp_send_hostname (NMSettingIP4Config *setting); +const char * nm_setting_ip4_config_get_dhcp_hostname (NMSettingIP4Config *setting); + +gboolean nm_setting_ip4_config_get_never_default (NMSettingIP4Config *setting); + +gboolean nm_setting_ip4_config_get_may_fail (NMSettingIP4Config *setting); + +G_END_DECLS + +#endif /* NM_SETTING_IP4_CONFIG_H */ diff --git a/libnm-util/nm-setting-ip6-config.c b/libnm-util/nm-setting-ip6-config.c new file mode 100644 index 00000000..32c3a4a2 --- /dev/null +++ b/libnm-util/nm-setting-ip6-config.c @@ -0,0 +1,1120 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * David Cantrell <dcantrel@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2010 Red Hat, Inc. + */ + +#include <string.h> + +#include <dbus/dbus-glib.h> +#include "nm-setting-ip6-config.h" +#include "nm-param-spec-specialized.h" +#include "nm-utils.h" +#include "nm-dbus-glib-types.h" + +GQuark +nm_setting_ip6_config_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-ip6-config-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_ip6_config_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_IP6_CONFIG_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_IP6_CONFIG_ERROR_MISSING_PROPERTY, "MissingProperty"), + /* The specified property was not allowed in combination with the current 'method' */ + ENUM_ENTRY (NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD, "NotAllowedForMethod"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingIP6ConfigError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING) + +#define NM_SETTING_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigPrivate)) + +typedef struct { + char *method; + GSList *dns; /* array of struct in6_addr */ + GSList *dns_search; /* list of strings */ + GSList *addresses; /* array of NMIP6Address */ + GSList *routes; /* array of NMIP6Route */ + gboolean ignore_auto_routes; + gboolean ignore_auto_dns; + gboolean never_default; + gboolean may_fail; +} NMSettingIP6ConfigPrivate; + + +enum { + PROP_0, + PROP_METHOD, + PROP_DNS, + PROP_DNS_SEARCH, + PROP_ADDRESSES, + PROP_ROUTES, + PROP_IGNORE_AUTO_ROUTES, + PROP_IGNORE_AUTO_DNS, + PROP_NEVER_DEFAULT, + PROP_MAY_FAIL, + + LAST_PROP +}; + +NMSetting * +nm_setting_ip6_config_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_IP6_CONFIG, NULL); +} + +const char * +nm_setting_ip6_config_get_method (NMSettingIP6Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->method; +} + +guint32 +nm_setting_ip6_config_get_num_dns (NMSettingIP6Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), 0); + + return g_slist_length (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns); +} + +const struct in6_addr * +nm_setting_ip6_config_get_dns (NMSettingIP6Config *setting, guint32 i) +{ + NMSettingIP6ConfigPrivate *priv; + + + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), 0); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->dns), NULL); + + return (const struct in6_addr *) g_slist_nth_data (priv->dns, i); +} + +gboolean +nm_setting_ip6_config_add_dns (NMSettingIP6Config *setting, const struct in6_addr *addr) +{ + NMSettingIP6ConfigPrivate *priv; + struct in6_addr *copy; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + for (iter = priv->dns; iter; iter = g_slist_next (iter)) { + if (!memcmp (addr, (struct in6_addr *) iter->data, sizeof (struct in6_addr))) + return FALSE; + } + + copy = g_malloc0 (sizeof (struct in6_addr)); + memcpy (copy, addr, sizeof (struct in6_addr)); + priv->dns = g_slist_append (priv->dns, copy); + + return TRUE; +} + +void +nm_setting_ip6_config_remove_dns (NMSettingIP6Config *setting, guint32 i) +{ + NMSettingIP6ConfigPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting)); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + elt = g_slist_nth (priv->dns, i); + g_return_if_fail (elt != NULL); + + g_free (elt->data); + priv->dns = g_slist_delete_link (priv->dns, elt); +} + +void +nm_setting_ip6_config_clear_dns (NMSettingIP6Config *setting) +{ + g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting)); + + nm_utils_slist_free (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns, g_free); + NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns = NULL; +} + +guint32 +nm_setting_ip6_config_get_num_dns_searches (NMSettingIP6Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), 0); + + return g_slist_length (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns_search); +} + +const char * +nm_setting_ip6_config_get_dns_search (NMSettingIP6Config *setting, guint32 i) +{ + NMSettingIP6ConfigPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->dns_search), NULL); + + return (const char *) g_slist_nth_data (priv->dns_search, i); +} + +gboolean +nm_setting_ip6_config_add_dns_search (NMSettingIP6Config *setting, + const char *dns_search) +{ + NMSettingIP6ConfigPrivate *priv; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE); + g_return_val_if_fail (dns_search != NULL, FALSE); + g_return_val_if_fail (dns_search[0] != '\0', FALSE); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + for (iter = priv->dns_search; iter; iter = g_slist_next (iter)) { + if (!strcmp (dns_search, (char *) iter->data)) + return FALSE; + } + + priv->dns_search = g_slist_append (priv->dns_search, g_strdup (dns_search)); + return TRUE; +} + +void +nm_setting_ip6_config_remove_dns_search (NMSettingIP6Config *setting, guint32 i) +{ + NMSettingIP6ConfigPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting)); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + elt = g_slist_nth (priv->dns_search, i); + g_return_if_fail (elt != NULL); + + g_free (elt->data); + priv->dns_search = g_slist_delete_link (priv->dns_search, elt); +} + +void +nm_setting_ip6_config_clear_dns_searches (NMSettingIP6Config *setting) +{ + g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting)); + + nm_utils_slist_free (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns_search, g_free); + NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns_search = NULL; +} + +guint32 +nm_setting_ip6_config_get_num_addresses (NMSettingIP6Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), 0); + + return g_slist_length (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->addresses); +} + +NMIP6Address * +nm_setting_ip6_config_get_address (NMSettingIP6Config *setting, guint32 i) +{ + NMSettingIP6ConfigPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->addresses), NULL); + + return (NMIP6Address *) g_slist_nth_data (priv->addresses, i); +} + +gboolean +nm_setting_ip6_config_add_address (NMSettingIP6Config *setting, + NMIP6Address *address) +{ + NMSettingIP6ConfigPrivate *priv; + NMIP6Address *copy; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE); + g_return_val_if_fail (address != NULL, FALSE); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + for (iter = priv->addresses; iter; iter = g_slist_next (iter)) { + if (nm_ip6_address_compare ((NMIP6Address *) iter->data, address)) + return FALSE; + } + + copy = nm_ip6_address_dup (address); + g_return_val_if_fail (copy != NULL, FALSE); + + priv->addresses = g_slist_append (priv->addresses, copy); + return TRUE; +} + +void +nm_setting_ip6_config_remove_address (NMSettingIP6Config *setting, guint32 i) +{ + NMSettingIP6ConfigPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting)); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + elt = g_slist_nth (priv->addresses, i); + g_return_if_fail (elt != NULL); + + nm_ip6_address_unref ((NMIP6Address *) elt->data); + priv->addresses = g_slist_delete_link (priv->addresses, elt); +} + +void +nm_setting_ip6_config_clear_addresses (NMSettingIP6Config *setting) +{ + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + + g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting)); + + nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip6_address_unref); + priv->addresses = NULL; +} + +guint32 +nm_setting_ip6_config_get_num_routes (NMSettingIP6Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), 0); + + return g_slist_length (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->routes); +} + +NMIP6Route * +nm_setting_ip6_config_get_route (NMSettingIP6Config *setting, guint32 i) +{ + NMSettingIP6ConfigPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->routes), NULL); + + return (NMIP6Route *) g_slist_nth_data (priv->routes, i); +} + +gboolean +nm_setting_ip6_config_add_route (NMSettingIP6Config *setting, + NMIP6Route *route) +{ + NMSettingIP6ConfigPrivate *priv; + NMIP6Route *copy; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE); + g_return_val_if_fail (route != NULL, FALSE); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + for (iter = priv->routes; iter; iter = g_slist_next (iter)) { + if (nm_ip6_route_compare ((NMIP6Route *) iter->data, route)) + return FALSE; + } + + copy = nm_ip6_route_dup (route); + g_return_val_if_fail (copy != NULL, FALSE); + + priv->routes = g_slist_append (priv->routes, copy); + return TRUE; +} + +void +nm_setting_ip6_config_remove_route (NMSettingIP6Config *setting, guint32 i) +{ + NMSettingIP6ConfigPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting)); + + priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + elt = g_slist_nth (priv->routes, i); + g_return_if_fail (elt != NULL); + + nm_ip6_route_unref ((NMIP6Route *) elt->data); + priv->routes = g_slist_delete_link (priv->routes, elt); +} + +void +nm_setting_ip6_config_clear_routes (NMSettingIP6Config *setting) +{ + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + + g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting)); + + nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip6_route_unref); + priv->routes = NULL; +} + +gboolean +nm_setting_ip6_config_get_ignore_auto_routes (NMSettingIP6Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ignore_auto_routes; +} + +gboolean +nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ignore_auto_dns; +} + +gboolean +nm_setting_ip6_config_get_never_default (NMSettingIP6Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->never_default; +} + +gboolean +nm_setting_ip6_config_get_may_fail (NMSettingIP6Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->may_fail; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting); + + if (!priv->method) { + g_set_error (error, + NM_SETTING_IP6_CONFIG_ERROR, + NM_SETTING_IP6_CONFIG_ERROR_MISSING_PROPERTY, + NM_SETTING_IP6_CONFIG_METHOD); + return FALSE; + } + + if (!strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { + if (!priv->addresses) { + g_set_error (error, + NM_SETTING_IP6_CONFIG_ERROR, + NM_SETTING_IP6_CONFIG_ERROR_MISSING_PROPERTY, + NM_SETTING_IP6_CONFIG_ADDRESSES); + return FALSE; + } + } else if ( !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) + || !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) + || !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) { + if (g_slist_length (priv->dns)) { + g_set_error (error, + NM_SETTING_IP6_CONFIG_ERROR, + NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD, + NM_SETTING_IP6_CONFIG_DNS); + return FALSE; + } + + if (g_slist_length (priv->dns_search)) { + g_set_error (error, + NM_SETTING_IP6_CONFIG_ERROR, + NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD, + NM_SETTING_IP6_CONFIG_DNS_SEARCH); + return FALSE; + } + + if (g_slist_length (priv->addresses)) { + g_set_error (error, + NM_SETTING_IP6_CONFIG_ERROR, + NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD, + NM_SETTING_IP6_CONFIG_ADDRESSES); + return FALSE; + } + } else if (!strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { + /* nothing to do */ + } else { + g_set_error (error, + NM_SETTING_IP6_CONFIG_ERROR, + NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY, + NM_SETTING_IP6_CONFIG_METHOD); + return FALSE; + } + + return TRUE; +} + + +static void +nm_setting_ip6_config_init (NMSettingIP6Config *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_IP6_CONFIG_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (object); + + g_free (priv->method); + + if (priv->dns) + g_slist_free (priv->dns); + + nm_utils_slist_free (priv->dns_search, g_free); + nm_utils_slist_free (priv->addresses, g_free); + nm_utils_slist_free (priv->routes, g_free); + + G_OBJECT_CLASS (nm_setting_ip6_config_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_METHOD: + g_free (priv->method); + priv->method = g_value_dup_string (value); + break; + case PROP_DNS: + nm_utils_slist_free (priv->dns, g_free); + priv->dns = nm_utils_ip6_dns_from_gvalue (value); + break; + case PROP_DNS_SEARCH: + nm_utils_slist_free (priv->dns_search, g_free); + priv->dns_search = g_value_dup_boxed (value); + break; + case PROP_ADDRESSES: + nm_utils_slist_free (priv->addresses, g_free); + priv->addresses = nm_utils_ip6_addresses_from_gvalue (value); + break; + case PROP_ROUTES: + nm_utils_slist_free (priv->routes, g_free); + priv->routes = nm_utils_ip6_routes_from_gvalue (value); + break; + case PROP_IGNORE_AUTO_ROUTES: + priv->ignore_auto_routes = g_value_get_boolean (value); + break; + case PROP_IGNORE_AUTO_DNS: + priv->ignore_auto_dns = g_value_get_boolean (value); + break; + case PROP_NEVER_DEFAULT: + priv->never_default = g_value_get_boolean (value); + break; + case PROP_MAY_FAIL: + priv->may_fail = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_METHOD: + g_value_set_string (value, priv->method); + break; + case PROP_DNS: + nm_utils_ip6_dns_to_gvalue (priv->dns, value); + break; + case PROP_DNS_SEARCH: + g_value_set_boxed (value, priv->dns_search); + break; + case PROP_ADDRESSES: + nm_utils_ip6_addresses_to_gvalue (priv->addresses, value); + break; + case PROP_ROUTES: + nm_utils_ip6_routes_to_gvalue (priv->routes, value); + break; + case PROP_IGNORE_AUTO_ROUTES: + g_value_set_boolean (value, priv->ignore_auto_routes); + break; + case PROP_IGNORE_AUTO_DNS: + g_value_set_boolean (value, priv->ignore_auto_dns); + break; + case PROP_NEVER_DEFAULT: + g_value_set_boolean (value, priv->never_default); + break; + case PROP_MAY_FAIL: + g_value_set_boolean (value, priv->may_fail); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingIP6ConfigPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ + /** + * NMSettingIP6Config:method: + * + * IPv6 configuration method. If 'auto' is specified then the appropriate + * automatic method (DHCP, PPP, router advertisement, etc) is used for the + * interface and most other properties can be left unset. If 'link-local' + * is specified, then an IPv6 link-local address will be assigned to the + * interface. If 'manual' is specified, static IP addressing is used and + * at least one IP address must be given in the 'addresses' property. If + * 'ignored' is specified, IPv6 configuration is not done. This property + * must be set. NOTE: the 'shared' method are not yet supported. + **/ + g_object_class_install_property + (object_class, PROP_METHOD, + g_param_spec_string (NM_SETTING_IP6_CONFIG_METHOD, + "Method", + "IPv6 configuration method. If 'auto' is specified " + "then the appropriate automatic method (DHCP, PPP, " + "router advertisement, etc) is used for the " + "interface and most other properties can be left " + "unset. If 'link-local' is specified, then an " + "IPv6 link-local address will be assigned to the " + "interface. If 'manual' is specified, static IP " + "addressing is used and at least one IP address " + "must be given in the 'addresses' property. If " + "'ignored' is specified, IPv6 configuration is not " + "done. This property must be set. NOTE: the " + "'shared' method are not yet supported.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP6Config:dns: + * + * Array of DNS servers, where each member of the array is a byte array + * containing the IPv6 address of the DNS server (in network byte order). + * For the 'auto' method, these DNS servers are appended to those (if any) + * returned by automatic configuration. DNS servers cannot be used with + * the 'shared' or 'link-local' methods as there is no usptream network. In + * all other methods, these DNS servers are used as the only DNS servers for + * this connection. + **/ + g_object_class_install_property + (object_class, PROP_DNS, + _nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_DNS, + "DNS", + "Array of DNS servers, where each member of the " + "array is a byte array containing the IPv6 address " + "of the DNS server (in network byte order). For " + "the 'auto' method, these DNS servers are " + "appended to those (if any) returned by automatic " + "configuration. DNS servers cannot be used with " + "the 'shared' or 'link-local' methods as there is " + "no usptream network. In all other methods, " + "these DNS servers are used as the only DNS " + "servers for this connection.", + DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP6Config:dns-search: + * + * List of DNS search domains. For the 'auto' method, these search domains + * are appended to those returned by automatic configuration. Search domains + * cannot be used with the 'shared' or 'link-local' methods as there is no + * upstream network. In all other methods, these search domains are used + * as the only search domains for this connection. + **/ + g_object_class_install_property + (object_class, PROP_DNS_SEARCH, + _nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_DNS_SEARCH, + "DNS search", + "List of DNS search domains. For the 'auto' " + "method, these search domains are appended to " + "those returned by automatic configuration. " + "Search domains cannot be used with the 'shared' " + "or 'link-local' methods as there is no upstream " + "network. In all other methods, these search " + "domains are used as the only search domains for " + "this connection.", + DBUS_TYPE_G_LIST_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP6Config:addresses: + * + * Array of IPv6 address structures. Each IPv6 address structure is + * composed of 3 members, the first being a byte array containing the IPv6 + * address (network byte order), the second a 32-bit integer containing the + * IPv6 address prefix, and the third a byte array containing the IPv6 + * address (network byte order) of the gateway associated with this address, + * if any. If no gateway is given, the third element should be given as + * all zeros. For the 'auto' method, given IP addresses are appended to + * those returned by automatic configuration. Addresses cannot be used with + * the 'shared' or 'link-local' methods as the interface is automatically + * assigned an address with these methods. + **/ + g_object_class_install_property + (object_class, PROP_ADDRESSES, + _nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_ADDRESSES, + "Addresses", + "Array of IPv6 address structures. Each IPv6 " + "address structure is composed of 3 members, the " + "first being a byte array containing the IPv6 " + "address (network byte order), the second a " + "32-bit integer containing the IPv6 address " + "prefix, and the third a byte array containing " + "the IPv6 address (network byte order) of the " + "gateway associated with this address, if any. " + "If no gateway is given, the third element should " + "be given as all zeros. For the 'auto' method, " + "given IP addresses are appended to those returned " + "by automatic configuration. Addresses cannot be " + "used with the 'shared' or 'link-local' methods " + "as the interface is automatically assigned an " + "address with these methods.", + DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP6Config:routes: + * + * Array of IPv6 route structures. Each IPv6 route structure is composed + * of 4 members; the first being the destination IPv6 network or + * address (network byte order) as a byte array, the second the destination + * network or address IPv6 prefix, the third being the next-hop IPv6 address + * (network byte order) if any, and the fourth being the route metric. For + * the 'auto' method, given IP routes are appended to those returned by + * automatic configuration. Routes cannot be used with the 'shared' or + * 'link-local' methods because there is no upstream network. + **/ + g_object_class_install_property + (object_class, PROP_ROUTES, + _nm_param_spec_specialized (NM_SETTING_IP6_CONFIG_ROUTES, + "Routes", + "Array of IPv6 route structures. Each IPv6 route " + "structure is composed of 4 members; the first " + "being the destination IPv6 network or address " + "(network byte order) as a byte array, the second " + "the destination network or address IPv6 prefix, " + "the third being the next-hop IPv6 address " + "(network byte order) if any, and the fourth " + "being the route metric. For the 'auto' method, " + "given IP routes are appended to those returned " + "by automatic configuration. Routes cannot be " + "used with the 'shared' or 'link-local' methods " + "because there is no upstream network.", + DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP6Config:ignore-auto-routes: + * + * When the method is set to 'auto' and this property is set to TRUE, + * automatically configured routes are ignored and only routes specified + * in #NMSettingIP6Config:routes, if any, are used. + **/ + g_object_class_install_property + (object_class, PROP_IGNORE_AUTO_ROUTES, + g_param_spec_boolean (NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES, + "Ignore automatic routes", + "When the method is set to 'auto' and this property " + "is set to TRUE, automatically configured routes are " + "ignored and only routes specified in the 'routes' " + "property, if any, are used.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP6Config:ignore-auto-dns: + * + * When the method is set to 'auto' and this property is set to TRUE, + * automatically configured nameservers and search domains are ignored + * and only nameservers and search domains specified in + * #NMSettingIP6Config:dns and #NMSettingIP6Config:dns-search, if any, are + * used. + **/ + g_object_class_install_property + (object_class, PROP_IGNORE_AUTO_DNS, + g_param_spec_boolean (NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS, + "Ignore DHCPv6/RDNSS DNS", + "When the method is set to 'auto' and this property " + "is set to TRUE, automatically configured nameservers " + "and search domains are ignored and only nameservers " + "and search domains specified in 'dns' and 'dns-search' " + "properties, if any, are used.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP6Config:never-default: + * + * If TRUE, this connection will never be the default IPv6 connection, + * meaning it will never be assigned the default IPv6 route by NetworkManager. + **/ + g_object_class_install_property + (object_class, PROP_NEVER_DEFAULT, + g_param_spec_boolean (NM_SETTING_IP6_CONFIG_NEVER_DEFAULT, + "Never default", + "If TRUE, this connection will never be the default " + "IPv6 connection, meaning it will never be assigned " + "the default IPv6 route by NetworkManager.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingIP6Config:may-fail: + * + * If TRUE, allow overall network configuration to proceed even if IPv6 + * configuration times out. Note that at least one IP configuration + * must succeed or overall network configuration will still fail. For + * example, in IPv4-only networks, setting this property to TRUE allows + * the overall network configuration to succeed if IPv6 configuration fails + * but IPv4 configuration completes successfully. + **/ + g_object_class_install_property + (object_class, PROP_MAY_FAIL, + g_param_spec_boolean (NM_SETTING_IP6_CONFIG_MAY_FAIL, + "May Fail", + "If TRUE, allow overall network configuration to " + "proceed even if IPv6 configuration times out. " + "Note that at least one IP configuration must " + "succeed or overall network configuration will still " + "fail. For example, in IPv4-only networks, setting " + "this property to TRUE allows the overall network " + "configuration to succeed if IPv6 configuration " + "fails but IPv4 configuration completes successfully.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); +} + +/********************************************************************/ + +struct NMIP6Address { + guint32 refcount; + struct in6_addr address; + guint32 prefix; + struct in6_addr gateway; +}; + +NMIP6Address * +nm_ip6_address_new (void) +{ + NMIP6Address *address; + + address = g_malloc0 (sizeof (NMIP6Address)); + address->refcount = 1; + return address; +} + +NMIP6Address * +nm_ip6_address_dup (NMIP6Address *source) +{ + NMIP6Address *address; + + g_return_val_if_fail (source != NULL, NULL); + g_return_val_if_fail (source->refcount > 0, NULL); + + address = nm_ip6_address_new (); + address->prefix = source->prefix; + memcpy (&address->address, &source->address, sizeof (struct in6_addr)); + memcpy (&address->gateway, &source->gateway, sizeof (struct in6_addr)); + + return address; +} + +void +nm_ip6_address_ref (NMIP6Address *address) +{ + g_return_if_fail (address != NULL); + g_return_if_fail (address->refcount > 0); + + address->refcount++; +} + +void +nm_ip6_address_unref (NMIP6Address *address) +{ + g_return_if_fail (address != NULL); + g_return_if_fail (address->refcount > 0); + + address->refcount--; + if (address->refcount == 0) { + memset (address, 0, sizeof (NMIP6Address)); + g_free (address); + } +} + +gboolean +nm_ip6_address_compare (NMIP6Address *address, NMIP6Address *other) +{ + g_return_val_if_fail (address != NULL, FALSE); + g_return_val_if_fail (address->refcount > 0, FALSE); + + g_return_val_if_fail (other != NULL, FALSE); + g_return_val_if_fail (other->refcount > 0, FALSE); + + if ( memcmp (&address->address, &other->address, sizeof (struct in6_addr)) + || address->prefix != other->prefix + || memcmp (&address->gateway, &other->gateway, sizeof (struct in6_addr))) + return FALSE; + return TRUE; +} + +const struct in6_addr * +nm_ip6_address_get_address (NMIP6Address *address) +{ + g_return_val_if_fail (address != NULL, 0); + g_return_val_if_fail (address->refcount > 0, 0); + + return &address->address; +} + +void +nm_ip6_address_set_address (NMIP6Address *address, const struct in6_addr *addr) +{ + g_return_if_fail (address != NULL); + g_return_if_fail (address->refcount > 0); + g_return_if_fail (addr != NULL); + + memcpy (&address->address, addr, sizeof (struct in6_addr)); +} + +guint32 +nm_ip6_address_get_prefix (NMIP6Address *address) +{ + g_return_val_if_fail (address != NULL, 0); + g_return_val_if_fail (address->refcount > 0, 0); + + return address->prefix; +} + +void +nm_ip6_address_set_prefix (NMIP6Address *address, guint32 prefix) +{ + g_return_if_fail (address != NULL); + g_return_if_fail (address->refcount > 0); + + address->prefix = prefix; +} + +const struct in6_addr * +nm_ip6_address_get_gateway (NMIP6Address *address) +{ + g_return_val_if_fail (address != NULL, 0); + g_return_val_if_fail (address->refcount > 0, 0); + + return &address->gateway; +} + +void +nm_ip6_address_set_gateway (NMIP6Address *address, const struct in6_addr *gw) +{ + g_return_if_fail (address != NULL); + g_return_if_fail (address->refcount > 0); + g_return_if_fail (gw != NULL); + + memcpy (&address->gateway, gw, sizeof (struct in6_addr)); +} + +/********************************************************************/ + +struct NMIP6Route { + guint32 refcount; + + struct in6_addr dest; + guint32 prefix; + struct in6_addr next_hop; + guint32 metric; /* lower metric == more preferred */ +}; + +NMIP6Route * +nm_ip6_route_new (void) +{ + NMIP6Route *route; + + route = g_malloc0 (sizeof (NMIP6Route)); + route->refcount = 1; + return route; +} + +NMIP6Route * +nm_ip6_route_dup (NMIP6Route *source) +{ + NMIP6Route *route; + + g_return_val_if_fail (source != NULL, NULL); + g_return_val_if_fail (source->refcount > 0, NULL); + + route = nm_ip6_route_new (); + route->prefix = source->prefix; + route->metric = source->metric; + memcpy (&route->dest, &source->dest, sizeof (struct in6_addr)); + memcpy (&route->next_hop, &source->next_hop, sizeof (struct in6_addr)); + + return route; +} + +void +nm_ip6_route_ref (NMIP6Route *route) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + + route->refcount++; +} + +void +nm_ip6_route_unref (NMIP6Route *route) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + + route->refcount--; + if (route->refcount == 0) { + memset (route, 0, sizeof (NMIP6Route)); + g_free (route); + } +} + +gboolean +nm_ip6_route_compare (NMIP6Route *route, NMIP6Route *other) +{ + g_return_val_if_fail (route != NULL, FALSE); + g_return_val_if_fail (route->refcount > 0, FALSE); + + g_return_val_if_fail (other != NULL, FALSE); + g_return_val_if_fail (other->refcount > 0, FALSE); + + if ( memcmp (&route->dest, &other->dest, sizeof (struct in6_addr)) + || route->prefix != other->prefix + || memcmp (&route->next_hop, &other->next_hop, sizeof (struct in6_addr)) + || route->metric != other->metric) + return FALSE; + return TRUE; +} + +const struct in6_addr * +nm_ip6_route_get_dest (NMIP6Route *route) +{ + g_return_val_if_fail (route != NULL, 0); + g_return_val_if_fail (route->refcount > 0, 0); + + return &route->dest; +} + +void +nm_ip6_route_set_dest (NMIP6Route *route, const struct in6_addr *dest) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + g_return_if_fail (dest != NULL); + + memcpy (&route->dest, dest, sizeof (struct in6_addr)); +} + +guint32 +nm_ip6_route_get_prefix (NMIP6Route *route) +{ + g_return_val_if_fail (route != NULL, 0); + g_return_val_if_fail (route->refcount > 0, 0); + + return route->prefix; +} + +void +nm_ip6_route_set_prefix (NMIP6Route *route, guint32 prefix) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + + route->prefix = prefix; +} + +const struct in6_addr * +nm_ip6_route_get_next_hop (NMIP6Route *route) +{ + g_return_val_if_fail (route != NULL, 0); + g_return_val_if_fail (route->refcount > 0, 0); + + return &route->next_hop; +} + +void +nm_ip6_route_set_next_hop (NMIP6Route *route, const struct in6_addr *next_hop) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + g_return_if_fail (next_hop != NULL); + + memcpy (&route->next_hop, next_hop, sizeof (struct in6_addr)); +} + +guint32 +nm_ip6_route_get_metric (NMIP6Route *route) +{ + g_return_val_if_fail (route != NULL, 0); + g_return_val_if_fail (route->refcount > 0, 0); + + return route->metric; +} + +void +nm_ip6_route_set_metric (NMIP6Route *route, guint32 metric) +{ + g_return_if_fail (route != NULL); + g_return_if_fail (route->refcount > 0); + + route->metric = metric; +} diff --git a/libnm-util/nm-setting-ip6-config.h b/libnm-util/nm-setting-ip6-config.h new file mode 100644 index 00000000..06e5c5c1 --- /dev/null +++ b/libnm-util/nm-setting-ip6-config.h @@ -0,0 +1,170 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * David Cantrell <dcantrel@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2010 Red Hat, Inc. + */ + +#ifndef NM_SETTING_IP6_CONFIG_H +#define NM_SETTING_IP6_CONFIG_H + +#include <arpa/inet.h> + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_IP6_CONFIG (nm_setting_ip6_config_get_type ()) +#define NM_SETTING_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6Config)) +#define NM_SETTING_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_IP6CONFIG, NMSettingIP6ConfigClass)) +#define NM_IS_SETTING_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_IP6_CONFIG)) +#define NM_IS_SETTING_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_IP6_CONFIG)) +#define NM_SETTING_IP6_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigClass)) + +#define NM_SETTING_IP6_CONFIG_SETTING_NAME "ipv6" + +typedef enum +{ + NM_SETTING_IP6_CONFIG_ERROR_UNKNOWN = 0, + NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY, + NM_SETTING_IP6_CONFIG_ERROR_MISSING_PROPERTY, + NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD +} NMSettingIP6ConfigError; + +#define NM_TYPE_SETTING_IP6_CONFIG_ERROR (nm_setting_ip6_config_error_get_type ()) +GType nm_setting_ip6_config_error_get_type (void); + +#define NM_SETTING_IP6_CONFIG_ERROR nm_setting_ip6_config_error_quark () +GQuark nm_setting_ip6_config_error_quark (void); + +#define NM_SETTING_IP6_CONFIG_METHOD "method" +#define NM_SETTING_IP6_CONFIG_DNS "dns" +#define NM_SETTING_IP6_CONFIG_DNS_SEARCH "dns-search" +#define NM_SETTING_IP6_CONFIG_ADDRESSES "addresses" +#define NM_SETTING_IP6_CONFIG_ROUTES "routes" +#define NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes" +#define NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns" +#define NM_SETTING_IP6_CONFIG_NEVER_DEFAULT "never-default" +#define NM_SETTING_IP6_CONFIG_MAY_FAIL "may-fail" + +#define NM_SETTING_IP6_CONFIG_METHOD_IGNORE "ignore" +#define NM_SETTING_IP6_CONFIG_METHOD_AUTO "auto" +#define NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL "link-local" +#define NM_SETTING_IP6_CONFIG_METHOD_MANUAL "manual" +#define NM_SETTING_IP6_CONFIG_METHOD_SHARED "shared" + + +typedef struct NMIP6Address NMIP6Address; + +NMIP6Address * nm_ip6_address_new (void); +NMIP6Address * nm_ip6_address_dup (NMIP6Address *source); +void nm_ip6_address_ref (NMIP6Address *address); +void nm_ip6_address_unref (NMIP6Address *address); +/* Return TRUE if addresses are identical */ +gboolean nm_ip6_address_compare (NMIP6Address *address, NMIP6Address *other); + +const struct in6_addr *nm_ip6_address_get_address (NMIP6Address *address); +void nm_ip6_address_set_address (NMIP6Address *address, + const struct in6_addr *addr); + +guint32 nm_ip6_address_get_prefix (NMIP6Address *address); +void nm_ip6_address_set_prefix (NMIP6Address *address, + guint32 prefix); + +const struct in6_addr *nm_ip6_address_get_gateway (NMIP6Address *address); +void nm_ip6_address_set_gateway (NMIP6Address *address, + const struct in6_addr *gw); + +typedef struct NMIP6Route NMIP6Route; + +NMIP6Route * nm_ip6_route_new (void); +NMIP6Route * nm_ip6_route_dup (NMIP6Route *route); +void nm_ip6_route_ref (NMIP6Route *route); +void nm_ip6_route_unref (NMIP6Route *route); +/* Return TRUE if routes are identical */ +gboolean nm_ip6_route_compare (NMIP6Route *route, NMIP6Route *other); + +const struct in6_addr *nm_ip6_route_get_dest (NMIP6Route *route); +void nm_ip6_route_set_dest (NMIP6Route *route, + const struct in6_addr *dest); + +guint32 nm_ip6_route_get_prefix (NMIP6Route *route); +void nm_ip6_route_set_prefix (NMIP6Route *route, + guint32 prefix); + +const struct in6_addr *nm_ip6_route_get_next_hop (NMIP6Route *route); +void nm_ip6_route_set_next_hop (NMIP6Route *route, + const struct in6_addr *next_hop); + +guint32 nm_ip6_route_get_metric (NMIP6Route *route); +void nm_ip6_route_set_metric (NMIP6Route *route, + guint32 metric); + +typedef struct { + NMSetting parent; +} NMSettingIP6Config; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingIP6ConfigClass; + +GType nm_setting_ip6_config_get_type (void); + +NMSetting * nm_setting_ip6_config_new (void); +const char * nm_setting_ip6_config_get_method (NMSettingIP6Config *setting); + +guint32 nm_setting_ip6_config_get_num_dns (NMSettingIP6Config *setting); +const struct in6_addr *nm_setting_ip6_config_get_dns (NMSettingIP6Config *setting, guint32 i); +gboolean nm_setting_ip6_config_add_dns (NMSettingIP6Config *setting, const struct in6_addr *dns); +void nm_setting_ip6_config_remove_dns (NMSettingIP6Config *setting, guint32 i); +void nm_setting_ip6_config_clear_dns (NMSettingIP6Config *setting); + +guint32 nm_setting_ip6_config_get_num_dns_searches (NMSettingIP6Config *setting); +const char * nm_setting_ip6_config_get_dns_search (NMSettingIP6Config *setting, guint32 i); +gboolean nm_setting_ip6_config_add_dns_search (NMSettingIP6Config *setting, const char *dns_search); +void nm_setting_ip6_config_remove_dns_search (NMSettingIP6Config *setting, guint32 i); +void nm_setting_ip6_config_clear_dns_searches (NMSettingIP6Config *setting); + +guint32 nm_setting_ip6_config_get_num_addresses (NMSettingIP6Config *setting); +NMIP6Address * nm_setting_ip6_config_get_address (NMSettingIP6Config *setting, guint32 i); +gboolean nm_setting_ip6_config_add_address (NMSettingIP6Config *setting, NMIP6Address *address); +void nm_setting_ip6_config_remove_address (NMSettingIP6Config *setting, guint32 i); +void nm_setting_ip6_config_clear_addresses (NMSettingIP6Config *setting); + +guint32 nm_setting_ip6_config_get_num_routes (NMSettingIP6Config *setting); +NMIP6Route * nm_setting_ip6_config_get_route (NMSettingIP6Config *setting, guint32 i); +gboolean nm_setting_ip6_config_add_route (NMSettingIP6Config *setting, NMIP6Route *route); +void nm_setting_ip6_config_remove_route (NMSettingIP6Config *setting, guint32 i); +void nm_setting_ip6_config_clear_routes (NMSettingIP6Config *setting); +gboolean nm_setting_ip6_config_get_ignore_auto_routes (NMSettingIP6Config *setting); + +gboolean nm_setting_ip6_config_get_ignore_auto_dns (NMSettingIP6Config *setting); +gboolean nm_setting_ip6_config_get_never_default (NMSettingIP6Config *setting); +gboolean nm_setting_ip6_config_get_may_fail (NMSettingIP6Config *setting); + +G_END_DECLS + +#endif /* NM_SETTING_IP6_CONFIG_H */ diff --git a/libnm-util/nm-setting-olpc-mesh.c b/libnm-util/nm-setting-olpc-mesh.c new file mode 100644 index 00000000..1653bb07 --- /dev/null +++ b/libnm-util/nm-setting-olpc-mesh.c @@ -0,0 +1,296 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * Sjoerd Simons <sjoerd.simons@collabora.co.uk> + * Daniel Drake <dsd@laptop.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + * (C) Copyright 2009 One Laptop per Child + */ + +#include <string.h> +#include <netinet/ether.h> +#include <dbus/dbus-glib.h> + +#include "NetworkManager.h" +#include "nm-setting-olpc-mesh.h" +#include "nm-param-spec-specialized.h" +#include "nm-utils.h" +#include "nm-dbus-glib-types.h" +#include "nm-utils-private.h" + +GQuark +nm_setting_olpc_mesh_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-olpc-mesh-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_olpc_mesh_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_OLPC_MESH_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY, "MissingProperty"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingOlpcMeshError", values); + } + return etype; +} + +static void nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting); + +G_DEFINE_TYPE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING) + +#define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate)) + +typedef struct { + GByteArray *ssid; + guint32 channel; + GByteArray *dhcp_anycast_addr; +} NMSettingOlpcMeshPrivate; + +enum { + PROP_0, + PROP_SSID, + PROP_CHANNEL, + PROP_DHCP_ANYCAST_ADDRESS, + + LAST_PROP +}; + +/** + * nm_setting_olpc_mesh_new: + * + * Creates a new #NMSettingOlpcMesh object with default values. + * + * Returns: the new empty #NMSettingOlpcMesh object + **/ +NMSetting *nm_setting_olpc_mesh_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_OLPC_MESH, NULL); +} + +static void +nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_OLPC_MESH_SETTING_NAME, NULL); +} + +const GByteArray * +nm_setting_olpc_mesh_get_ssid (NMSettingOlpcMesh *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), NULL); + + return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->ssid; +} + +guint32 +nm_setting_olpc_mesh_get_channel (NMSettingOlpcMesh *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), 0); + + return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->channel; +} + +const GByteArray * +nm_setting_olpc_mesh_get_dhcp_anycast_address (NMSettingOlpcMesh *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), NULL); + + return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->dhcp_anycast_addr; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (setting); + + if (!priv->ssid) { + g_set_error (error, + NM_SETTING_OLPC_MESH_ERROR, + NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY, + NM_SETTING_OLPC_MESH_SSID); + return FALSE; + } + + if (!priv->ssid->len || priv->ssid->len > 32) { + g_set_error (error, + NM_SETTING_OLPC_MESH_ERROR, + NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, + NM_SETTING_OLPC_MESH_SSID); + return FALSE; + } + + if (priv->channel == 0 || priv->channel > 13) { + g_set_error (error, + NM_SETTING_OLPC_MESH_ERROR, + NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, + NM_SETTING_OLPC_MESH_CHANNEL); + return FALSE; + } + + if (priv->dhcp_anycast_addr && priv->dhcp_anycast_addr->len != ETH_ALEN) { + g_set_error (error, + NM_SETTING_OLPC_MESH_ERROR, + NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, + NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS); + return FALSE; + } + + return TRUE; +} + +static void +finalize (GObject *object) +{ + NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (object); + + if (priv->ssid) + g_byte_array_free (priv->ssid, TRUE); + if (priv->dhcp_anycast_addr) + g_byte_array_free (priv->dhcp_anycast_addr, TRUE); + + G_OBJECT_CLASS (nm_setting_olpc_mesh_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_SSID: + if (priv->ssid) + g_byte_array_free (priv->ssid, TRUE); + priv->ssid = g_value_dup_boxed (value); + break; + case PROP_CHANNEL: + priv->channel = g_value_get_uint (value); + break; + case PROP_DHCP_ANYCAST_ADDRESS: + if (priv->dhcp_anycast_addr) + g_byte_array_free (priv->dhcp_anycast_addr, TRUE); + priv->dhcp_anycast_addr = g_value_dup_boxed (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingOlpcMesh *setting = NM_SETTING_OLPC_MESH (object); + + switch (prop_id) { + case PROP_SSID: + g_value_set_boxed (value, nm_setting_olpc_mesh_get_ssid (setting)); + break; + case PROP_CHANNEL: + g_value_set_uint (value, nm_setting_olpc_mesh_get_channel (setting)); + break; + case PROP_DHCP_ANYCAST_ADDRESS: + g_value_set_boxed (value, nm_setting_olpc_mesh_get_dhcp_anycast_address (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingOlpcMeshPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ + /** + * NMSettingOlpcMesh:ssid: + * + * SSID of the mesh network to join. + **/ + g_object_class_install_property + (object_class, PROP_SSID, + _nm_param_spec_specialized (NM_SETTING_OLPC_MESH_SSID, + "SSID", + "SSID of the mesh network to join.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingOlpcMesh:channel: + * + * Channel on which the mesh network to join is located. + **/ + g_object_class_install_property + (object_class, PROP_CHANNEL, + g_param_spec_uint (NM_SETTING_OLPC_MESH_CHANNEL, + "Channel", + "Channel on which the mesh network to join is located.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingOlpcMesh:dhcp-anycast-address: + * + * Anycast DHCP address used when requesting an IP address via DHCP. The + * specific anycast address used determines which DHCP server class answers + * the request. + **/ + g_object_class_install_property + (object_class, PROP_DHCP_ANYCAST_ADDRESS, + _nm_param_spec_specialized (NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, + "Anycast DHCP MAC address", + "Anycast DHCP MAC address used when " + "requesting an IP address via DHCP. The " + "specific anycast address used determines " + "which DHCP server class answers the " + "the request.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + +} diff --git a/libnm-util/nm-setting-olpc-mesh.h b/libnm-util/nm-setting-olpc-mesh.h new file mode 100644 index 00000000..84abd126 --- /dev/null +++ b/libnm-util/nm-setting-olpc-mesh.h @@ -0,0 +1,84 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * Sjoerd Simons <sjoerd.simons@collabora.co.uk> + * Daniel Drake <dsd@laptop.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + * (C) Copyright 2009 One Laptop per Child + */ + +#ifndef NM_SETTING_OLPC_MESH_H +#define NM_SETTING_OLPC_MESH_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OLPC_MESH (nm_setting_olpc_mesh_get_type ()) +#define NM_SETTING_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMesh)) +#define NM_SETTING_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass)) +#define NM_IS_SETTING_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_OLPC_MESH)) +#define NM_IS_SETTING_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_OLPC_MESH)) +#define NM_SETTING_OLPC_MESH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass)) + +#define NM_SETTING_OLPC_MESH_SETTING_NAME "802-11-olpc-mesh" + +typedef enum +{ + NM_SETTING_OLPC_MESH_ERROR_UNKNOWN = 0, + NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY, + NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY +} NMSettingOlpcMeshError; + +#define NM_TYPE_SETTING_OLPC_MESH_ERROR (nm_setting_olpc_mesh_error_get_type ()) +GType nm_setting_olpc_mesh_error_get_type (void); + +#define NM_SETTING_OLPC_MESH_ERROR nm_setting_olpc_mesh_error_quark () +GQuark nm_setting_olpc_mesh_error_quark (void); + +#define NM_SETTING_OLPC_MESH_SSID "ssid" +#define NM_SETTING_OLPC_MESH_CHANNEL "channel" +#define NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS "dhcp-anycast-address" + +typedef struct { + NMSetting parent; +} NMSettingOlpcMesh; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingOlpcMeshClass; + +GType nm_setting_olpc_mesh_get_type (void); + +NMSetting * nm_setting_olpc_mesh_new (void); +const GByteArray *nm_setting_olpc_mesh_get_ssid (NMSettingOlpcMesh *setting); +guint32 nm_setting_olpc_mesh_get_channel (NMSettingOlpcMesh *setting); +const GByteArray *nm_setting_olpc_mesh_get_dhcp_anycast_address (NMSettingOlpcMesh *setting); + +G_END_DECLS + +#endif /* NM_SETTING_OLPC_MESH_H */ diff --git a/libnm-util/nm-setting-ppp.c b/libnm-util/nm-setting-ppp.c new file mode 100644 index 00000000..fd6043f1 --- /dev/null +++ b/libnm-util/nm-setting-ppp.c @@ -0,0 +1,730 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include "nm-setting-ppp.h" + +GQuark +nm_setting_ppp_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-ppp-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_ppp_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_PPP_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_PPP_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_PPP_ERROR_MISSING_PROPERTY, "MissingProperty"), + /* The 'require-mppe' option is not allowed in conjunction with the specified authentication. */ + ENUM_ENTRY (NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED, "RequireMPPENotAllowed"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingPPPError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingPPP, nm_setting_ppp, NM_TYPE_SETTING) + +#define NM_SETTING_PPP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPP, NMSettingPPPPrivate)) + +typedef struct { + gboolean noauth; + gboolean refuse_eap; + gboolean refuse_pap; + gboolean refuse_chap; + gboolean refuse_mschap; + gboolean refuse_mschapv2; + gboolean nobsdcomp; + gboolean nodeflate; + gboolean no_vj_comp; + gboolean require_mppe; + gboolean require_mppe_128; + gboolean mppe_stateful; + gboolean crtscts; + guint32 baud; + guint32 mru; + guint32 mtu; + guint32 lcp_echo_failure; + guint32 lcp_echo_interval; +} NMSettingPPPPrivate; + +enum { + PROP_0, + PROP_NOAUTH, + PROP_REFUSE_EAP, + PROP_REFUSE_PAP, + PROP_REFUSE_CHAP, + PROP_REFUSE_MSCHAP, + PROP_REFUSE_MSCHAPV2, + PROP_NOBSDCOMP, + PROP_NODEFLATE, + PROP_NO_VJ_COMP, + PROP_REQUIRE_MPPE, + PROP_REQUIRE_MPPE_128, + PROP_MPPE_STATEFUL, + PROP_CRTSCTS, + PROP_BAUD, + PROP_MRU, + PROP_MTU, + PROP_LCP_ECHO_FAILURE, + PROP_LCP_ECHO_INTERVAL, + + LAST_PROP +}; + +NMSetting * +nm_setting_ppp_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_PPP, NULL); +} + +gboolean +nm_setting_ppp_get_noauth (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->noauth; +} + +gboolean +nm_setting_ppp_get_refuse_eap (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->refuse_eap; +} + +gboolean +nm_setting_ppp_get_refuse_pap (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->refuse_pap; +} + +gboolean +nm_setting_ppp_get_refuse_chap (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->refuse_chap; +} + +gboolean +nm_setting_ppp_get_refuse_mschap (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->refuse_mschap; +} + +gboolean +nm_setting_ppp_get_refuse_mschapv2 (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->refuse_mschapv2; +} + +gboolean +nm_setting_ppp_get_nobsdcomp (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->nobsdcomp; +} + +gboolean +nm_setting_ppp_get_nodeflate (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->nodeflate; +} + +gboolean +nm_setting_ppp_get_no_vj_comp (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->no_vj_comp; +} + +gboolean +nm_setting_ppp_get_require_mppe (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->require_mppe; +} + +gboolean +nm_setting_ppp_get_require_mppe_128 (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->require_mppe_128; +} + +gboolean +nm_setting_ppp_get_mppe_stateful (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->mppe_stateful; +} + +gboolean +nm_setting_ppp_get_crtscts (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->crtscts; +} + +guint32 +nm_setting_ppp_get_baud (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), 0); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->baud; +} + +guint32 +nm_setting_ppp_get_mru (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), 0); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->mru; +} + +guint32 +nm_setting_ppp_get_mtu (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), 0); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->mtu; +} + +guint32 +nm_setting_ppp_get_lcp_echo_failure (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), 0); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->lcp_echo_failure; +} + +guint32 +nm_setting_ppp_get_lcp_echo_interval (NMSettingPPP *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPP (setting), 0); + + return NM_SETTING_PPP_GET_PRIVATE (setting)->lcp_echo_interval; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingPPPPrivate *priv = NM_SETTING_PPP_GET_PRIVATE (setting); + + /* FIXME: Do we even want this or can we just let pppd evaluate the options? */ + if (priv->mru > 0) { + if (priv->mru < 128 || priv->mru > 16384) { + g_set_error (error, + NM_SETTING_PPP_ERROR, + NM_SETTING_PPP_ERROR_INVALID_PROPERTY, + NM_SETTING_PPP_MRU); + return FALSE; + } + } + + if (priv->lcp_echo_failure > 0) { + /* lcp_echo_interval must also be non-zero */ + if (priv->lcp_echo_interval == 0) { + g_set_error (error, + NM_SETTING_PPP_ERROR, + NM_SETTING_PPP_ERROR_INVALID_PROPERTY, + NM_SETTING_PPP_LCP_ECHO_FAILURE); + return FALSE; + } + } + + return TRUE; +} + +static void +nm_setting_ppp_init (NMSettingPPP *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_PPP_SETTING_NAME, NULL); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingPPPPrivate *priv = NM_SETTING_PPP_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_NOAUTH: + priv->noauth = g_value_get_boolean (value); + break; + case PROP_REFUSE_EAP: + priv->refuse_eap = g_value_get_boolean (value); + break; + case PROP_REFUSE_PAP: + priv->refuse_pap = g_value_get_boolean (value); + break; + case PROP_REFUSE_CHAP: + priv->refuse_chap = g_value_get_boolean (value); + break; + case PROP_REFUSE_MSCHAP: + priv->refuse_mschap = g_value_get_boolean (value); + break; + case PROP_REFUSE_MSCHAPV2: + priv->refuse_mschapv2 = g_value_get_boolean (value); + break; + case PROP_NOBSDCOMP: + priv->nobsdcomp = g_value_get_boolean (value); + break; + case PROP_NODEFLATE: + priv->nodeflate = g_value_get_boolean (value); + break; + case PROP_NO_VJ_COMP: + priv->no_vj_comp = g_value_get_boolean (value); + break; + case PROP_REQUIRE_MPPE: + priv->require_mppe = g_value_get_boolean (value); + break; + case PROP_REQUIRE_MPPE_128: + priv->require_mppe_128 = g_value_get_boolean (value); + break; + case PROP_MPPE_STATEFUL: + priv->mppe_stateful = g_value_get_boolean (value); + break; + case PROP_CRTSCTS: + priv->crtscts = g_value_get_boolean (value); + break; + case PROP_BAUD: + priv->baud = g_value_get_uint (value); + break; + case PROP_MRU: + priv->mru = g_value_get_uint (value); + break; + case PROP_MTU: + priv->mtu = g_value_get_uint (value); + break; + case PROP_LCP_ECHO_FAILURE: + priv->lcp_echo_failure = g_value_get_uint (value); + break; + case PROP_LCP_ECHO_INTERVAL: + priv->lcp_echo_interval = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingPPP *setting = NM_SETTING_PPP (object); + + switch (prop_id) { + case PROP_NOAUTH: + g_value_set_boolean (value, nm_setting_ppp_get_noauth (setting)); + break; + case PROP_REFUSE_EAP: + g_value_set_boolean (value, nm_setting_ppp_get_refuse_eap (setting)); + break; + case PROP_REFUSE_PAP: + g_value_set_boolean (value, nm_setting_ppp_get_refuse_pap (setting)); + break; + case PROP_REFUSE_CHAP: + g_value_set_boolean (value, nm_setting_ppp_get_refuse_chap (setting)); + break; + case PROP_REFUSE_MSCHAP: + g_value_set_boolean (value, nm_setting_ppp_get_refuse_mschap (setting)); + break; + case PROP_REFUSE_MSCHAPV2: + g_value_set_boolean (value, nm_setting_ppp_get_refuse_mschapv2 (setting)); + break; + case PROP_NOBSDCOMP: + g_value_set_boolean (value, nm_setting_ppp_get_nobsdcomp (setting)); + break; + case PROP_NODEFLATE: + g_value_set_boolean (value, nm_setting_ppp_get_nodeflate (setting)); + break; + case PROP_NO_VJ_COMP: + g_value_set_boolean (value, nm_setting_ppp_get_no_vj_comp (setting)); + break; + case PROP_REQUIRE_MPPE: + g_value_set_boolean (value, nm_setting_ppp_get_require_mppe (setting)); + break; + case PROP_REQUIRE_MPPE_128: + g_value_set_boolean (value, nm_setting_ppp_get_require_mppe_128 (setting)); + break; + case PROP_MPPE_STATEFUL: + g_value_set_boolean (value, nm_setting_ppp_get_mppe_stateful (setting)); + break; + case PROP_CRTSCTS: + g_value_set_boolean (value, nm_setting_ppp_get_crtscts (setting)); + break; + case PROP_BAUD: + g_value_set_uint (value, nm_setting_ppp_get_baud (setting)); + break; + case PROP_MRU: + g_value_set_uint (value, nm_setting_ppp_get_mru (setting)); + break; + case PROP_MTU: + g_value_set_uint (value, nm_setting_ppp_get_mtu (setting)); + break; + case PROP_LCP_ECHO_FAILURE: + g_value_set_uint (value, nm_setting_ppp_get_lcp_echo_failure (setting)); + break; + case PROP_LCP_ECHO_INTERVAL: + g_value_set_uint (value, nm_setting_ppp_get_lcp_echo_interval (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_ppp_class_init (NMSettingPPPClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingPPPPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + parent_class->verify = verify; + + /* Properties */ + /** + * NMSettingPPP:noauth: + * + * If TRUE, do not require the other side (usually the PPP server) to + * authenticate itself to the client. If FALSE, require authentication from + * the remote side. In almost all cases, this should be TRUE. + **/ + g_object_class_install_property + (object_class, PROP_NOAUTH, + g_param_spec_boolean (NM_SETTING_PPP_NOAUTH, + "NoAuth", + "If TRUE, do not require the other side (usually the " + "PPP server) to authenticate itself to the client. " + "If FALSE, require authentication from the remote " + "side. In almost all cases, this should be TRUE.", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:refuse-eap: + * + * If TRUE, the EAP authentication method will not be used. + **/ + g_object_class_install_property + (object_class, PROP_REFUSE_EAP, + g_param_spec_boolean (NM_SETTING_PPP_REFUSE_EAP, + "Refuse EAP", + "If TRUE, the EAP authentication method will not be used.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:refuse-pap: + * + * If TRUE, the PAP authentication method will not be used. + **/ + g_object_class_install_property + (object_class, PROP_REFUSE_PAP, + g_param_spec_boolean (NM_SETTING_PPP_REFUSE_PAP, + "Refuse PAP", + "If TRUE, the PAP authentication method will not be used.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:refuse-chap: + * + * If TRUE, the CHAP authentication method will not be used. + **/ + g_object_class_install_property + (object_class, PROP_REFUSE_CHAP, + g_param_spec_boolean (NM_SETTING_PPP_REFUSE_CHAP, + "Refuse CHAP", + "If TRUE, the CHAP authentication method will not be used.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:refuse-mschap: + * + * If TRUE, the MSCHAP authentication method will not be used. + **/ + g_object_class_install_property + (object_class, PROP_REFUSE_MSCHAP, + g_param_spec_boolean (NM_SETTING_PPP_REFUSE_MSCHAP, + "Refuse MSCHAP", + "If TRUE, the MSCHAP authentication method will not be used.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:refuse-mschapv2: + * + * If TRUE, the MSCHAPv2 authentication method will not be used. + **/ + g_object_class_install_property + (object_class, PROP_REFUSE_MSCHAPV2, + g_param_spec_boolean (NM_SETTING_PPP_REFUSE_MSCHAPV2, + "Refuse MSCHAPv2", + "If TRUE, the MSCHAPv2 authentication method will not be used.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:nobsdcomp: + * + * If TRUE, BSD compression will not be requested. + **/ + g_object_class_install_property + (object_class, PROP_NOBSDCOMP, + g_param_spec_boolean (NM_SETTING_PPP_NOBSDCOMP, + "No BSD compression", + "If TRUE, BSD compression will not be requested.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingPPP:nodeflate: + * + * If TRUE, 'deflate' compression will not be requested. + **/ + g_object_class_install_property + (object_class, PROP_NODEFLATE, + g_param_spec_boolean (NM_SETTING_PPP_NODEFLATE, + "No deflate", + "If TRUE, 'deflate' compression will not be requested.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingPPP:no-vj-comp: + * + * If TRUE, Van Jacobsen TCP header compression will not be requested. + **/ + g_object_class_install_property + (object_class, PROP_NO_VJ_COMP, + g_param_spec_boolean (NM_SETTING_PPP_NO_VJ_COMP, + "No VJ compression", + "If TRUE, Van Jacobsen TCP header compression will not be requested.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingPPP:require-mppe: + * + * If TRUE, MPPE (Microsoft Point-to-Point Encrpytion) will be required for + * the PPP session. If either 64-bit or 128-bit MPPE is not available the + * session will fail. Note that MPPE is not used on mobile broadband + * connections. + **/ + g_object_class_install_property + (object_class, PROP_REQUIRE_MPPE, + g_param_spec_boolean (NM_SETTING_PPP_REQUIRE_MPPE, + "Require MPPE", + "If TRUE, MPPE (Microsoft Point-to-Point Encrpytion) " + "will be required for the PPP session. If either " + "64-bit or 128-bit MPPE is not available the session " + "will fail. Note that MPPE is not used on mobile " + "broadband connections.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:require-mppe-128: + * + * If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encrpytion) will be + * required for the PPP session, and the 'require-mppe' property must also + * be set to TRUE. If 128-bit MPPE is not available the session will fail. + **/ + g_object_class_install_property + (object_class, PROP_REQUIRE_MPPE_128, + g_param_spec_boolean (NM_SETTING_PPP_REQUIRE_MPPE_128, + "Require MPPE 128", + "If TRUE, 128-bit MPPE (Microsoft Point-to-Point " + "Encrpytion) will be required for the PPP session, " + "and the '" NM_SETTING_PPP_REQUIRE_MPPE "' property " + "must also be set to TRUE. If 128-bit MPPE is not " + "available the session will fail.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT| NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:mppe-stateful: + * + * If TRUE, stateful MPPE is used. See pppd documentation for more + * information on stateful MPPE.", + **/ + g_object_class_install_property + (object_class, PROP_MPPE_STATEFUL, + g_param_spec_boolean (NM_SETTING_PPP_MPPE_STATEFUL, + "MPPE stateful", + "If TRUE, stateful MPPE is used. See pppd documentation " + "for more information on stateful MPPE.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:crtscts: + * + * If TRUE, specify that pppd should set the serial port to use hardware + * flow control with RTS and CTS signals. This value should normally be + * set to FALSE. + **/ + g_object_class_install_property + (object_class, PROP_CRTSCTS, + g_param_spec_boolean (NM_SETTING_PPP_CRTSCTS, + "CRTSCTS", + "If TRUE, specify that pppd should set the serial " + "port to use hardware flow control with RTS and CTS " + "signals. This value should normally be set to " + "FALSE.", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:baud: + * + * If non-zero, instruct pppd to set the serial port to the specified + * baudrate. This value should normally be left as 0 to automatically + * choose the speed. + **/ + g_object_class_install_property + (object_class, PROP_BAUD, + g_param_spec_uint (NM_SETTING_PPP_BAUD, + "Baud", + "If non-zero, instruct pppd to set the serial port to " + "the specified baudrate. This value should normally be " + "left as 0 to automatically choose the speed.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingPPP:mru: + * + * If non-zero, instruct pppd to request that the peer send packets no + * larger than the specified size. If non-zero, the MRU should be between + * 128 and 16384. + */ + g_object_class_install_property + (object_class, PROP_MRU, + g_param_spec_uint (NM_SETTING_PPP_MRU, + "MRU", + "If non-zero, instruct pppd to request that the peer " + "send packets no larger than the specified size. If " + "non-zero, the MRU should be between 128 and 16384.", + 0, 16384, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPP:mtu: + * + * If non-zero, instruct pppd to send packets no larger than the specified + * size. + **/ + g_object_class_install_property + (object_class, PROP_MTU, + g_param_spec_uint (NM_SETTING_PPP_MTU, + "MTU", + "If non-zero, instruct pppd to send packets no larger " + "than the specified size.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingPPP:lcp-echo-failure: + * + * If non-zero, instruct pppd to presume the connection to the peer has + * failed if the specified number of LCP echo-requests go unanswered by the + * peer. The 'lcp-echo-interval' property must also be set to a non-zero + * value if this property is used. + **/ + g_object_class_install_property + (object_class, PROP_LCP_ECHO_FAILURE, + g_param_spec_uint (NM_SETTING_PPP_LCP_ECHO_FAILURE, + "LCP echo failure", + "If non-zero, instruct pppd to presume the connection to " + "the peer has failed if the specified number of LCP " + "echo-requests go unanswered by the peer. The " + "'" NM_SETTING_PPP_LCP_ECHO_INTERVAL "' property must " + "also be set to a non-zero value if this property is " + "used.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingPPP:lcp-echo-interval: + * + * If non-zero, instruct pppd to send an LCP echo-request frame to the peer + * every n seconds (where n is the specified value). Note that some PPP + * peers will respond to echo requests and some will not, and it is not + * possible to autodetect this. + **/ + g_object_class_install_property + (object_class, PROP_LCP_ECHO_INTERVAL, + g_param_spec_uint (NM_SETTING_PPP_LCP_ECHO_INTERVAL, + "LCP echo interval", + "If non-zero, instruct pppd to send an LCP echo-request " + "frame to the peer every n seconds (where n is the " + "specified value). Note that some PPP peers will respond " + "to echo requests and some will not, and it is not " + "possible to autodetect this.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); +} diff --git a/libnm-util/nm-setting-ppp.h b/libnm-util/nm-setting-ppp.h new file mode 100644 index 00000000..cfa1f57a --- /dev/null +++ b/libnm-util/nm-setting-ppp.h @@ -0,0 +1,113 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_PPP_H +#define NM_SETTING_PPP_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_PPP (nm_setting_ppp_get_type ()) +#define NM_SETTING_PPP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_PPP, NMSettingPPP)) +#define NM_SETTING_PPP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_PPP, NMSettingPPPClass)) +#define NM_IS_SETTING_PPP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_PPP)) +#define NM_IS_SETTING_PPP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_PPP)) +#define NM_SETTING_PPP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_PPP, NMSettingPPPClass)) + +#define NM_SETTING_PPP_SETTING_NAME "ppp" + +typedef enum +{ + NM_SETTING_PPP_ERROR_UNKNOWN = 0, + NM_SETTING_PPP_ERROR_INVALID_PROPERTY, + NM_SETTING_PPP_ERROR_MISSING_PROPERTY, + NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED +} NMSettingPPPError; + +#define NM_TYPE_SETTING_PPP_ERROR (nm_setting_ppp_error_get_type ()) +GType nm_setting_ppp_error_get_type (void); + +#define NM_SETTING_PPP_ERROR nm_setting_ppp_error_quark () +GQuark nm_setting_ppp_error_quark (void); + +#define NM_SETTING_PPP_NOAUTH "noauth" +#define NM_SETTING_PPP_REFUSE_EAP "refuse-eap" +#define NM_SETTING_PPP_REFUSE_PAP "refuse-pap" +#define NM_SETTING_PPP_REFUSE_CHAP "refuse-chap" +#define NM_SETTING_PPP_REFUSE_MSCHAP "refuse-mschap" +#define NM_SETTING_PPP_REFUSE_MSCHAPV2 "refuse-mschapv2" +#define NM_SETTING_PPP_NOBSDCOMP "nobsdcomp" +#define NM_SETTING_PPP_NODEFLATE "nodeflate" +#define NM_SETTING_PPP_NO_VJ_COMP "no-vj-comp" +#define NM_SETTING_PPP_REQUIRE_MPPE "require-mppe" +#define NM_SETTING_PPP_REQUIRE_MPPE_128 "require-mppe-128" +#define NM_SETTING_PPP_MPPE_STATEFUL "mppe-stateful" +#define NM_SETTING_PPP_CRTSCTS "crtscts" +#define NM_SETTING_PPP_BAUD "baud" +#define NM_SETTING_PPP_MRU "mru" +#define NM_SETTING_PPP_MTU "mtu" +#define NM_SETTING_PPP_LCP_ECHO_FAILURE "lcp-echo-failure" +#define NM_SETTING_PPP_LCP_ECHO_INTERVAL "lcp-echo-interval" + +typedef struct { + NMSetting parent; +} NMSettingPPP; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingPPPClass; + +GType nm_setting_ppp_get_type (void); + +NMSetting *nm_setting_ppp_new (void); +gboolean nm_setting_ppp_get_noauth (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_refuse_eap (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_refuse_pap (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_refuse_chap (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_refuse_mschap (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_refuse_mschapv2 (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_nobsdcomp (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_nodeflate (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_no_vj_comp (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_require_mppe (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_require_mppe_128 (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_mppe_stateful (NMSettingPPP *setting); +gboolean nm_setting_ppp_get_crtscts (NMSettingPPP *setting); +guint32 nm_setting_ppp_get_baud (NMSettingPPP *setting); +guint32 nm_setting_ppp_get_mru (NMSettingPPP *setting); +guint32 nm_setting_ppp_get_mtu (NMSettingPPP *setting); +guint32 nm_setting_ppp_get_lcp_echo_failure (NMSettingPPP *setting); +guint32 nm_setting_ppp_get_lcp_echo_interval (NMSettingPPP *setting); + +G_END_DECLS + +#endif /* NM_SETTING_PPP_H */ diff --git a/libnm-util/nm-setting-pppoe.c b/libnm-util/nm-setting-pppoe.c new file mode 100644 index 00000000..d1aba43d --- /dev/null +++ b/libnm-util/nm-setting-pppoe.c @@ -0,0 +1,274 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2010 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> +#include "nm-setting-pppoe.h" +#include "nm-setting-ppp.h" + +GQuark +nm_setting_pppoe_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-pppoe-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_pppoe_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_PPPOE_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_PPPOE_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_PPPOE_ERROR_MISSING_PROPERTY, "MissingProperty"), + /* The required PPP setting is missing */ + ENUM_ENTRY (NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING, "MissingPPPSetting"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingPPPOEError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingPPPOE, nm_setting_pppoe, NM_TYPE_SETTING) + +#define NM_SETTING_PPPOE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPPOE, NMSettingPPPOEPrivate)) + +typedef struct { + char *service; + char *username; + char *password; +} NMSettingPPPOEPrivate; + +enum { + PROP_0, + PROP_SERVICE, + PROP_USERNAME, + PROP_PASSWORD, + + LAST_PROP +}; + +NMSetting * +nm_setting_pppoe_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_PPPOE, NULL); +} + +const char * +nm_setting_pppoe_get_service (NMSettingPPPOE *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPPOE (setting), NULL); + + return NM_SETTING_PPPOE_GET_PRIVATE (setting)->service; +} + +const char * +nm_setting_pppoe_get_username (NMSettingPPPOE *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPPOE (setting), NULL); + + return NM_SETTING_PPPOE_GET_PRIVATE (setting)->username; +} + +const char * +nm_setting_pppoe_get_password (NMSettingPPPOE *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPPOE (setting), NULL); + + return NM_SETTING_PPPOE_GET_PRIVATE (setting)->password; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingPPPOEPrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (setting); + + if (!priv->username) { + g_set_error (error, + NM_SETTING_PPPOE_ERROR, + NM_SETTING_PPPOE_ERROR_MISSING_PROPERTY, + NM_SETTING_PPPOE_USERNAME); + return FALSE; + } else if (!strlen (priv->username)) { + g_set_error (error, + NM_SETTING_PPPOE_ERROR, + NM_SETTING_PPPOE_ERROR_INVALID_PROPERTY, + NM_SETTING_PPPOE_USERNAME); + return FALSE; + } + + if (priv->service && !strlen (priv->service)) { + g_set_error (error, + NM_SETTING_PPPOE_ERROR, + NM_SETTING_PPPOE_ERROR_INVALID_PROPERTY, + NM_SETTING_PPPOE_SERVICE); + return FALSE; + } + + return TRUE; +} + +static GPtrArray * +need_secrets (NMSetting *setting) +{ + NMSettingPPPOEPrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (setting); + GPtrArray *secrets; + + if (priv->password) + return NULL; + + secrets = g_ptr_array_sized_new (1); + g_ptr_array_add (secrets, NM_SETTING_PPPOE_PASSWORD); + + return secrets; +} + +static void +nm_setting_pppoe_init (NMSettingPPPOE *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_PPPOE_SETTING_NAME, NULL); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingPPPOEPrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_SERVICE: + g_free (priv->service); + priv->service = g_value_dup_string (value); + break; + case PROP_USERNAME: + g_free (priv->username); + priv->username = g_value_dup_string (value); + break; + case PROP_PASSWORD: + g_free (priv->password); + priv->password = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingPPPOE *setting = NM_SETTING_PPPOE (object); + + switch (prop_id) { + case PROP_SERVICE: + g_value_set_string (value, nm_setting_pppoe_get_service (setting)); + break; + case PROP_USERNAME: + g_value_set_string (value, nm_setting_pppoe_get_username (setting)); + break; + case PROP_PASSWORD: + g_value_set_string (value, nm_setting_pppoe_get_password (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_pppoe_class_init (NMSettingPPPOEClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingPPPOEPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + parent_class->verify = verify; + parent_class->need_secrets = need_secrets; + + /* Properties */ + /** + * NMSettingPPPOE:service: + * + * If specified, instruct PPPoE to only initiate sessions with access + * concentrators that provide the specified serivce. For most providers, + * this should be left blank. It is only required if there are multiple + * access concentrators or a specific service is known to be required. + **/ + g_object_class_install_property + (object_class, PROP_SERVICE, + g_param_spec_string (NM_SETTING_PPPOE_SERVICE, + "Service", + "If specified, instruct PPPoE to only initiate sessions " + "with access concentrators that provide the specified " + "serivce. For most providers, this should be left " + "blank. It is only required if there are multiple " + "access concentrators or a specific service is known " + "to be required.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPPOE:username: + * + * Username used to authenticate with the PPPoE service. + **/ + g_object_class_install_property + (object_class, PROP_USERNAME, + g_param_spec_string (NM_SETTING_PPPOE_USERNAME, + "Username", + "Username used to authenticate with the PPPoE service.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingPPPOE:password: + * + * Password used to authenticate with the PPPoE service. + **/ + g_object_class_install_property + (object_class, PROP_PASSWORD, + g_param_spec_string (NM_SETTING_PPPOE_PASSWORD, + "Password", + "Password used to authenticate with the PPPoE service.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); +} diff --git a/libnm-util/nm-setting-pppoe.h b/libnm-util/nm-setting-pppoe.h new file mode 100644 index 00000000..83e95d4e --- /dev/null +++ b/libnm-util/nm-setting-pppoe.h @@ -0,0 +1,83 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_PPPOE_H +#define NM_SETTING_PPPOE_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_PPPOE (nm_setting_pppoe_get_type ()) +#define NM_SETTING_PPPOE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_PPPOE, NMSettingPPPOE)) +#define NM_SETTING_PPPOE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_PPPOE, NMSettingPPPOEClass)) +#define NM_IS_SETTING_PPPOE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_PPPOE)) +#define NM_IS_SETTING_PPPOE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_PPPOE)) +#define NM_SETTING_PPPOE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_PPPOE, NMSettingPPPOEClass)) + +#define NM_SETTING_PPPOE_SETTING_NAME "pppoe" + +typedef enum +{ + NM_SETTING_PPPOE_ERROR_UNKNOWN = 0, + NM_SETTING_PPPOE_ERROR_INVALID_PROPERTY, + NM_SETTING_PPPOE_ERROR_MISSING_PROPERTY, + NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING +} NMSettingPPPOEError; + +#define NM_TYPE_SETTING_PPPOE_ERROR (nm_setting_pppoe_error_get_type ()) +GType nm_setting_pppoe_error_get_type (void); + +#define NM_SETTING_PPPOE_ERROR nm_setting_pppoe_error_quark () +GQuark nm_setting_pppoe_error_quark (void); + +#define NM_SETTING_PPPOE_SERVICE "service" +#define NM_SETTING_PPPOE_USERNAME "username" +#define NM_SETTING_PPPOE_PASSWORD "password" + +typedef struct { + NMSetting parent; +} NMSettingPPPOE; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingPPPOEClass; + +GType nm_setting_pppoe_get_type (void); + +NMSetting *nm_setting_pppoe_new (void); +const char *nm_setting_pppoe_get_service (NMSettingPPPOE *setting); +const char *nm_setting_pppoe_get_username (NMSettingPPPOE *setting); +const char *nm_setting_pppoe_get_password (NMSettingPPPOE *setting); + +G_END_DECLS + +#endif /* NM_SETTING_PPPOE_H */ diff --git a/libnm-util/nm-setting-serial.c b/libnm-util/nm-setting-serial.c new file mode 100644 index 00000000..7a20688a --- /dev/null +++ b/libnm-util/nm-setting-serial.c @@ -0,0 +1,314 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> + +#include "nm-setting-serial.h" +#include "nm-setting-ppp.h" + +GQuark +nm_setting_serial_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-serial-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_serial_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_SERIAL_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_SERIAL_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_SERIAL_ERROR_MISSING_PROPERTY, "MissingProperty"), + /* The required PPP setting is missing */ + ENUM_ENTRY (NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING, "MissingPPPSetting"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingSerialError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING) + +#define NM_SETTING_SERIAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_SERIAL, NMSettingSerialPrivate)) + +typedef struct { + guint baud; + guint bits; + char parity; + guint stopbits; + guint64 send_delay; +} NMSettingSerialPrivate; + + +enum { + PROP_0, + PROP_BAUD, + PROP_BITS, + PROP_PARITY, + PROP_STOPBITS, + PROP_SEND_DELAY, + + LAST_PROP +}; + +NMSetting * +nm_setting_serial_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_SERIAL, NULL); +} + +guint +nm_setting_serial_get_baud (NMSettingSerial *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), 0); + + return NM_SETTING_SERIAL_GET_PRIVATE (setting)->baud; +} + +guint +nm_setting_serial_get_bits (NMSettingSerial *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), 0); + + return NM_SETTING_SERIAL_GET_PRIVATE (setting)->bits; +} + +char +nm_setting_serial_get_parity (NMSettingSerial *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), 0); + + return NM_SETTING_SERIAL_GET_PRIVATE (setting)->parity; +} + +guint +nm_setting_serial_get_stopbits (NMSettingSerial *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), 0); + + return NM_SETTING_SERIAL_GET_PRIVATE (setting)->stopbits; +} + +guint64 +nm_setting_serial_get_send_delay (NMSettingSerial *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), 0); + + return NM_SETTING_SERIAL_GET_PRIVATE (setting)->send_delay; +} + +static gint +find_setting_by_name (gconstpointer a, gconstpointer b) +{ + NMSetting *setting = NM_SETTING (a); + const char *str = (const char *) b; + + return strcmp (nm_setting_get_name (setting), str); +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + /* Serial connections require a PPP setting */ + if (all_settings && + !g_slist_find_custom (all_settings, NM_SETTING_PPP_SETTING_NAME, find_setting_by_name)) { + g_set_error (error, + NM_SETTING_SERIAL_ERROR, + NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING, + NULL); + return FALSE; + } + + return TRUE; +} + +static void +nm_setting_serial_init (NMSettingSerial *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_SERIAL_SETTING_NAME, NULL); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingSerialPrivate *priv = NM_SETTING_SERIAL_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BAUD: + priv->baud = g_value_get_uint (value); + break; + case PROP_BITS: + priv->bits = g_value_get_uint (value); + break; + case PROP_PARITY: + priv->parity = g_value_get_char (value); + break; + case PROP_STOPBITS: + priv->stopbits = g_value_get_uint (value); + break; + case PROP_SEND_DELAY: + priv->send_delay = g_value_get_uint64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingSerial *setting = NM_SETTING_SERIAL (object); + + switch (prop_id) { + case PROP_BAUD: + g_value_set_uint (value, nm_setting_serial_get_baud (setting)); + break; + case PROP_BITS: + g_value_set_uint (value, nm_setting_serial_get_bits (setting)); + break; + case PROP_PARITY: + g_value_set_char (value, nm_setting_serial_get_parity (setting)); + break; + case PROP_STOPBITS: + g_value_set_uint (value, nm_setting_serial_get_stopbits (setting)); + break; + case PROP_SEND_DELAY: + g_value_set_uint64 (value, nm_setting_serial_get_send_delay (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_serial_class_init (NMSettingSerialClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingSerialPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + parent_class->verify = verify; + + /* Properties */ + + /** + * NMSettingSerial:baud: + * + * Speed to use for communication over the serial port. Note that this value + * usually has no effect for mobile broadband modems as they generally + * ignore speed settings and use the highest available speed. + **/ + g_object_class_install_property + (object_class, PROP_BAUD, + g_param_spec_uint (NM_SETTING_SERIAL_BAUD, + "Baud", + "Speed to use for communication over the serial port. " + "Note that this value usually has no effect for mobile " + "broadband modems as they generally ignore speed " + "settings and use the highest available speed.", + 0, G_MAXUINT, 57600, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingSerial:bits: + * + * Byte-width of the serial communication. + **/ + g_object_class_install_property + (object_class, PROP_BITS, + g_param_spec_uint (NM_SETTING_SERIAL_BITS, + "Bits", + "Byte-width of the serial communication. The 8 in " + "'8n1' for example.", + 5, 8, 8, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingSerial:parity: + * + * Parity setting of the serial port. Either 'E' for even parity, 'o' for + * odd parity, or 'n' for no parity. + **/ + g_object_class_install_property + (object_class, PROP_PARITY, + g_param_spec_char (NM_SETTING_SERIAL_PARITY, + "Parity", + "Parity setting of the serial port. Either 'E' for even " + "parity, 'o' for odd parity, or 'n' for no parity.", + 'E', 'o', 'n', + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingSerial:stopbits: + * + * Number of stop bits for communication on the serial port. Either 1 or 2. + * The 1 in '8n1' for example. + **/ + g_object_class_install_property + (object_class, PROP_STOPBITS, + g_param_spec_uint (NM_SETTING_SERIAL_STOPBITS, + "Stopbits", + "Number of stop bits for communication on the serial " + "port. Either 1 or 2. The 1 in '8n1' for example.", + 1, 2, 1, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingSerial:send-delay: + * + * Time to delay between each byte sent to the modem, in microseconds. + **/ + g_object_class_install_property + (object_class, PROP_SEND_DELAY, + g_param_spec_uint64 (NM_SETTING_SERIAL_SEND_DELAY, + "SendDelay", + "Time to delay between each byte sent to the modem, " + "in microseconds.", + 0, G_MAXUINT64, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); +} diff --git a/libnm-util/nm-setting-serial.h b/libnm-util/nm-setting-serial.h new file mode 100644 index 00000000..d39e5a79 --- /dev/null +++ b/libnm-util/nm-setting-serial.h @@ -0,0 +1,87 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_SERIAL_H +#define NM_SETTING_SERIAL_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_SERIAL (nm_setting_serial_get_type ()) +#define NM_SETTING_SERIAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_SERIAL, NMSettingSerial)) +#define NM_SETTING_SERIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_SERIAL, NMSettingSerialClass)) +#define NM_IS_SETTING_SERIAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_SERIAL)) +#define NM_IS_SETTING_SERIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_SERIAL)) +#define NM_SETTING_SERIAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_SERIAL, NMSettingSerialClass)) + +#define NM_SETTING_SERIAL_SETTING_NAME "serial" + +typedef enum +{ + NM_SETTING_SERIAL_ERROR_UNKNOWN = 0, + NM_SETTING_SERIAL_ERROR_INVALID_PROPERTY, + NM_SETTING_SERIAL_ERROR_MISSING_PROPERTY, + NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING +} NMSettingSerialError; + +#define NM_TYPE_SETTING_SERIAL_ERROR (nm_setting_serial_error_get_type ()) +GType nm_setting_serial_error_get_type (void); + +#define NM_SETTING_SERIAL_ERROR nm_setting_serial_error_quark () +GQuark nm_setting_serial_error_quark (void); + +#define NM_SETTING_SERIAL_BAUD "baud" +#define NM_SETTING_SERIAL_BITS "bits" +#define NM_SETTING_SERIAL_PARITY "parity" +#define NM_SETTING_SERIAL_STOPBITS "stopbits" +#define NM_SETTING_SERIAL_SEND_DELAY "send-delay" + +typedef struct { + NMSetting parent; +} NMSettingSerial; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingSerialClass; + +GType nm_setting_serial_get_type (void); + +NMSetting *nm_setting_serial_new (void); +guint nm_setting_serial_get_baud (NMSettingSerial *setting); +guint nm_setting_serial_get_bits (NMSettingSerial *setting); +char nm_setting_serial_get_parity (NMSettingSerial *setting); +guint nm_setting_serial_get_stopbits (NMSettingSerial *setting); +guint64 nm_setting_serial_get_send_delay (NMSettingSerial *setting); + +G_END_DECLS + +#endif /* NM_SETTING_SERIAL_H */ diff --git a/libnm-util/nm-setting-vpn.c b/libnm-util/nm-setting-vpn.c new file mode 100644 index 00000000..53b609e2 --- /dev/null +++ b/libnm-util/nm-setting-vpn.c @@ -0,0 +1,464 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> +#include <dbus/dbus-glib.h> +#include "nm-setting-vpn.h" +#include "nm-param-spec-specialized.h" +#include "nm-utils.h" +#include "nm-dbus-glib-types.h" + +GQuark +nm_setting_vpn_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-vpn-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_vpn_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_VPN_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_VPN_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_VPN_ERROR_MISSING_PROPERTY, "MissingProperty"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingVpnError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingVPN, nm_setting_vpn, NM_TYPE_SETTING) + +#define NM_SETTING_VPN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VPN, NMSettingVPNPrivate)) + +typedef struct { + char *service_type; + + /* username of the user requesting this connection, thus + * it's really only valid for user connections, and it also + * should never be saved out to persistent config. + */ + char *user_name; + + /* The hash table is created at setting object + * init time and should not be replaced. It is + * a char * -> char * mapping, and both the key + * and value are owned by the hash table, and should + * be allocated with functions whose value can be + * freed with g_free(). Should not contain secrets. + */ + GHashTable *data; + + /* The hash table is created at setting object + * init time and should not be replaced. It is + * a char * -> char * mapping, and both the key + * and value are owned by the hash table, and should + * be allocated with functions whose value can be + * freed with g_free(). Should contain secrets only. + */ + GHashTable *secrets; +} NMSettingVPNPrivate; + +enum { + PROP_0, + PROP_SERVICE_TYPE, + PROP_USER_NAME, + PROP_DATA, + PROP_SECRETS, + + LAST_PROP +}; + +NMSetting * +nm_setting_vpn_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_VPN, NULL); +} + +const char * +nm_setting_vpn_get_service_type (NMSettingVPN *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL); + + return NM_SETTING_VPN_GET_PRIVATE (setting)->service_type; +} + +const char * +nm_setting_vpn_get_user_name (NMSettingVPN *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL); + + return NM_SETTING_VPN_GET_PRIVATE (setting)->user_name; +} + +void +nm_setting_vpn_add_data_item (NMSettingVPN *setting, + const char *key, + const char *item) +{ + g_return_if_fail (NM_IS_SETTING_VPN (setting)); + g_return_if_fail (key != NULL); + g_return_if_fail (strlen (key) > 0); + g_return_if_fail (item != NULL); + g_return_if_fail (strlen (item) > 0); + + g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->data, + g_strdup (key), g_strdup (item)); +} + +const char * +nm_setting_vpn_get_data_item (NMSettingVPN *setting, const char *key) +{ + g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL); + + return (const char *) g_hash_table_lookup (NM_SETTING_VPN_GET_PRIVATE (setting)->data, key); +} + +void +nm_setting_vpn_remove_data_item (NMSettingVPN *setting, const char *key) +{ + g_return_if_fail (NM_IS_SETTING_VPN (setting)); + + g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->data, key); +} + +void +nm_setting_vpn_foreach_data_item (NMSettingVPN *setting, + VPNIterFunc func, + gpointer user_data) +{ + g_return_if_fail (NM_IS_SETTING_VPN (setting)); + + g_hash_table_foreach (NM_SETTING_VPN_GET_PRIVATE (setting)->data, + (GHFunc) func, user_data); +} + +void +nm_setting_vpn_add_secret (NMSettingVPN *setting, + const char *key, + const char *secret) +{ + g_return_if_fail (NM_IS_SETTING_VPN (setting)); + g_return_if_fail (key != NULL); + g_return_if_fail (strlen (key) > 0); + g_return_if_fail (secret != NULL); + g_return_if_fail (strlen (secret) > 0); + + g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, + g_strdup (key), g_strdup (secret)); +} + +const char * +nm_setting_vpn_get_secret (NMSettingVPN *setting, const char *key) +{ + g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL); + + return (const char *) g_hash_table_lookup (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, key); +} + +void +nm_setting_vpn_remove_secret (NMSettingVPN *setting, const char *key) +{ + g_return_if_fail (NM_IS_SETTING_VPN (setting)); + + g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, key); +} + +void +nm_setting_vpn_foreach_secret (NMSettingVPN *setting, + VPNIterFunc func, + gpointer user_data) +{ + g_return_if_fail (NM_IS_SETTING_VPN (setting)); + + g_hash_table_foreach (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, + (GHFunc) func, user_data); +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); + + if (!priv->service_type) { + g_set_error (error, + NM_SETTING_VPN_ERROR, + NM_SETTING_VPN_ERROR_MISSING_PROPERTY, + NM_SETTING_VPN_SERVICE_TYPE); + return FALSE; + } + + if (!strlen (priv->service_type)) { + g_set_error (error, + NM_SETTING_VPN_ERROR, + NM_SETTING_VPN_ERROR_INVALID_PROPERTY, + NM_SETTING_VPN_SERVICE_TYPE); + return FALSE; + } + + /* default username can be NULL, but can't be zero-length */ + if (priv->user_name && !strlen (priv->user_name)) { + g_set_error (error, + NM_SETTING_VPN_ERROR, + NM_SETTING_VPN_ERROR_INVALID_PROPERTY, + NM_SETTING_VPN_USER_NAME); + return FALSE; + } + + return TRUE; +} + +static gboolean +update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error) +{ + NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); + char *str; + + g_return_val_if_fail (key != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + if (!G_VALUE_HOLDS_STRING (value)) { + g_set_error (error, NM_SETTING_ERROR, + NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, + "%s", key); + return FALSE; + } + + str = g_value_dup_string (value); + if (!str || !strlen (str)) { + g_set_error (error, NM_SETTING_ERROR, + NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, + "Secret %s was empty", key); + g_free (str); + return FALSE; + } + + g_hash_table_insert (priv->secrets, g_strdup (key), str); + return TRUE; +} + +static void +destroy_one_secret (gpointer data) +{ + char *secret = (char *) data; + + /* Don't leave the secret lying around in memory */ + memset (secret, 0, strlen (secret)); + g_free (secret); +} + +static void +nm_setting_vpn_init (NMSettingVPN *setting) +{ + NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); + + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_VPN_SETTING_NAME, NULL); + priv->data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + priv->secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_one_secret); +} + +static void +finalize (GObject *object) +{ + NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (object); + + g_free (priv->service_type); + g_free (priv->user_name); + g_hash_table_destroy (priv->data); + g_hash_table_destroy (priv->secrets); + + G_OBJECT_CLASS (nm_setting_vpn_parent_class)->finalize (object); +} + +static void +copy_hash (gpointer key, gpointer value, gpointer user_data) +{ + g_hash_table_insert ((GHashTable *) user_data, g_strdup (key), g_strdup (value)); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (object); + GHashTable *new_hash; + + switch (prop_id) { + case PROP_SERVICE_TYPE: + g_free (priv->service_type); + priv->service_type = g_value_dup_string (value); + break; + case PROP_USER_NAME: + g_free (priv->user_name); + priv->user_name = g_value_dup_string (value); + break; + case PROP_DATA: + /* Must make a deep copy of the hash table here... */ + g_hash_table_remove_all (priv->data); + new_hash = g_value_get_boxed (value); + if (new_hash) + g_hash_table_foreach (new_hash, copy_hash, priv->data); + break; + case PROP_SECRETS: + /* Must make a deep copy of the hash table here... */ + g_hash_table_remove_all (priv->secrets); + new_hash = g_value_get_boxed (value); + if (new_hash) + g_hash_table_foreach (new_hash, copy_hash, priv->secrets); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingVPN *setting = NM_SETTING_VPN (object); + NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_SERVICE_TYPE: + g_value_set_string (value, nm_setting_vpn_get_service_type (setting)); + break; + case PROP_USER_NAME: + g_value_set_string (value, nm_setting_vpn_get_user_name (setting)); + break; + case PROP_DATA: + g_value_set_boxed (value, priv->data); + break; + case PROP_SECRETS: + g_value_set_boxed (value, priv->secrets); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_vpn_class_init (NMSettingVPNClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingVPNPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + parent_class->update_one_secret = update_one_secret; + + /* Properties */ + /** + * NMSettingVPN:service-type: + * + * D-Bus service name of the VPN plugin that this setting uses to connect + * to its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc + * plugin. + **/ + g_object_class_install_property + (object_class, PROP_SERVICE_TYPE, + g_param_spec_string (NM_SETTING_VPN_SERVICE_TYPE, + "Service type", + "D-Bus service name of the VPN plugin that this " + "setting uses to connect to its network. i.e. " + "org.freedesktop.NetworkManager.vpnc for the vpnc " + "plugin.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettinVPN:user-name: + * + * User name of the currently logged in user for connections provided by the + * user settings service. This name is provided to the VPN plugin to use in + * lieu of a custom username provided by that VPN plugins specific + * configuration. The VPN plugin itself decides which user name to use. + **/ + g_object_class_install_property + (object_class, PROP_USER_NAME, + g_param_spec_string (NM_SETTING_VPN_USER_NAME, + "User name", + "User name of the currently logged in user for " + "connections provided by the user settings service. " + "This name is provided to the VPN plugin to use in " + "lieu of a custom username provided by that VPN " + "plugins specific configuration. The VPN plugin " + "itself decides which user name to use.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingVPN:data: + * + * Dictionary of key/value pairs of VPN plugin specific data. Both keys + * and values must be strings. + **/ + g_object_class_install_property + (object_class, PROP_DATA, + _nm_param_spec_specialized (NM_SETTING_VPN_DATA, + "Data", + "Dictionary of key/value pairs of VPN plugin " + "specific data. Both keys and values must be " + "strings.", + DBUS_TYPE_G_MAP_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingVPN:secrets: + * + * Dictionary of key/value pairs of VPN plugin specific secrets like + * passwords or private keys. Both keys and values must be strings. + **/ + g_object_class_install_property + (object_class, PROP_SECRETS, + _nm_param_spec_specialized (NM_SETTING_VPN_SECRETS, + "Secrets", + "Dictionary of key/value pairs of VPN plugin " + "specific secrets like passwords or private keys." + " Both keys and values must be strings.", + DBUS_TYPE_G_MAP_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); +} + diff --git a/libnm-util/nm-setting-vpn.h b/libnm-util/nm-setting-vpn.h new file mode 100644 index 00000000..9c684bbf --- /dev/null +++ b/libnm-util/nm-setting-vpn.h @@ -0,0 +1,106 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_VPN_H +#define NM_SETTING_VPN_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_VPN (nm_setting_vpn_get_type ()) +#define NM_SETTING_VPN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_VPN, NMSettingVPN)) +#define NM_SETTING_VPN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_VPN, NMSettingVPNClass)) +#define NM_IS_SETTING_VPN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_VPN)) +#define NM_IS_SETTING_VPN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_VPN)) +#define NM_SETTING_VPN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_VPN, NMSettingVPNClass)) + +#define NM_SETTING_VPN_SETTING_NAME "vpn" + +typedef enum +{ + NM_SETTING_VPN_ERROR_UNKNOWN = 0, + NM_SETTING_VPN_ERROR_INVALID_PROPERTY, + NM_SETTING_VPN_ERROR_MISSING_PROPERTY, +} NMSettingVpnError; + +#define NM_TYPE_SETTING_VPN_ERROR (nm_setting_vpn_error_get_type ()) +GType nm_setting_vpn_error_get_type (void); + +#define NM_SETTING_VPN_ERROR nm_setting_vpn_error_quark () +GQuark nm_setting_vpn_error_quark (void); + +#define NM_SETTING_VPN_SERVICE_TYPE "service-type" +#define NM_SETTING_VPN_USER_NAME "user-name" +#define NM_SETTING_VPN_DATA "data" +#define NM_SETTING_VPN_SECRETS "secrets" + +typedef struct { + NMSetting parent; +} NMSettingVPN; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingVPNClass; + +typedef void (*VPNIterFunc) (const char *key, const char *value, gpointer user_data); + +GType nm_setting_vpn_get_type (void); + +NMSetting *nm_setting_vpn_new (void); +const char *nm_setting_vpn_get_service_type (NMSettingVPN *setting); +const char *nm_setting_vpn_get_user_name (NMSettingVPN *setting); + +void nm_setting_vpn_add_data_item (NMSettingVPN *setting, + const char *key, + const char *item); +const char * nm_setting_vpn_get_data_item (NMSettingVPN *setting, + const char *key); +void nm_setting_vpn_remove_data_item (NMSettingVPN *setting, + const char *key); +void nm_setting_vpn_foreach_data_item (NMSettingVPN *setting, + VPNIterFunc func, + gpointer user_data); + +void nm_setting_vpn_add_secret (NMSettingVPN *setting, + const char *key, + const char *secret); +const char * nm_setting_vpn_get_secret (NMSettingVPN *setting, + const char *key); +void nm_setting_vpn_remove_secret (NMSettingVPN *setting, + const char *key); +void nm_setting_vpn_foreach_secret (NMSettingVPN *setting, + VPNIterFunc func, + gpointer user_data); + +G_END_DECLS + +#endif /* NM_SETTING_VPN_H */ diff --git a/libnm-util/nm-setting-wired.c b/libnm-util/nm-setting-wired.c new file mode 100644 index 00000000..2f252433 --- /dev/null +++ b/libnm-util/nm-setting-wired.c @@ -0,0 +1,384 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <net/ethernet.h> +#include <dbus/dbus-glib.h> +#include "nm-setting-wired.h" +#include "nm-param-spec-specialized.h" +#include "nm-utils.h" +#include "nm-utils-private.h" + +GQuark +nm_setting_wired_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-wired-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_wired_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_WIRED_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_WIRED_ERROR_MISSING_PROPERTY, "MissingProperty"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingWiredError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING) + +#define NM_SETTING_WIRED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRED, NMSettingWiredPrivate)) + +typedef struct { + char *port; + guint32 speed; + char *duplex; + gboolean auto_negotiate; + GByteArray *mac_address; + guint32 mtu; +} NMSettingWiredPrivate; + +enum { + PROP_0, + PROP_PORT, + PROP_SPEED, + PROP_DUPLEX, + PROP_AUTO_NEGOTIATE, + PROP_MAC_ADDRESS, + PROP_MTU, + + LAST_PROP +}; + +NMSetting * +nm_setting_wired_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIRED, NULL); +} + +const char * +nm_setting_wired_get_port (NMSettingWired *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE (setting)->port; +} + +guint32 +nm_setting_wired_get_speed (NMSettingWired *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0); + + return NM_SETTING_WIRED_GET_PRIVATE (setting)->speed; +} + +const char * +nm_setting_wired_get_duplex (NMSettingWired *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE (setting)->duplex; +} + +gboolean +nm_setting_wired_get_auto_negotiate (NMSettingWired *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE); + + return NM_SETTING_WIRED_GET_PRIVATE (setting)->auto_negotiate; +} + +const GByteArray * +nm_setting_wired_get_mac_address (NMSettingWired *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address; +} + +guint32 +nm_setting_wired_get_mtu (NMSettingWired *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0); + + return NM_SETTING_WIRED_GET_PRIVATE (setting)->mtu; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting); + const char *valid_ports[] = { "tp", "aui", "bnc", "mii", NULL }; + const char *valid_duplex[] = { "half", "full", NULL }; + + if (priv->port && !_nm_utils_string_in_list (priv->port, valid_ports)) { + g_set_error (error, + NM_SETTING_WIRED_ERROR, + NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRED_PORT); + return FALSE; + } + + if (priv->duplex && !_nm_utils_string_in_list (priv->duplex, valid_duplex)) { + g_set_error (error, + NM_SETTING_WIRED_ERROR, + NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRED_DUPLEX); + return FALSE; + } + + if (priv->mac_address && priv->mac_address->len != ETH_ALEN) { + g_set_error (error, + NM_SETTING_WIRED_ERROR, + NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRED_MAC_ADDRESS); + return FALSE; + } + + return TRUE; +} + +static void +nm_setting_wired_init (NMSettingWired *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_WIRED_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (object); + + g_free (priv->port); + g_free (priv->duplex); + + if (priv->mac_address) + g_byte_array_free (priv->mac_address, TRUE); + + G_OBJECT_CLASS (nm_setting_wired_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PORT: + g_free (priv->port); + priv->port = g_value_dup_string (value); + break; + case PROP_SPEED: + priv->speed = g_value_get_uint (value); + break; + case PROP_DUPLEX: + g_free (priv->duplex); + priv->duplex = g_value_dup_string (value); + break; + case PROP_AUTO_NEGOTIATE: + priv->auto_negotiate = g_value_get_boolean (value); + break; + case PROP_MAC_ADDRESS: + if (priv->mac_address) + g_byte_array_free (priv->mac_address, TRUE); + priv->mac_address = g_value_dup_boxed (value); + break; + case PROP_MTU: + priv->mtu = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingWired *setting = NM_SETTING_WIRED (object); + + switch (prop_id) { + case PROP_PORT: + g_value_set_string (value, nm_setting_wired_get_port (setting)); + break; + case PROP_SPEED: + g_value_set_uint (value, nm_setting_wired_get_speed (setting)); + break; + case PROP_DUPLEX: + g_value_set_string (value, nm_setting_wired_get_duplex (setting)); + break; + case PROP_AUTO_NEGOTIATE: + g_value_set_boolean (value, nm_setting_wired_get_auto_negotiate (setting)); + break; + case PROP_MAC_ADDRESS: + g_value_set_boxed (value, nm_setting_wired_get_mac_address (setting)); + break; + case PROP_MTU: + g_value_set_uint (value, nm_setting_wired_get_mtu (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_wired_class_init (NMSettingWiredClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingWiredPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ + /** + * NMSettingWired:port: + * + * Specific port type to use if multiple the device supports multiple + * attachment methods. One of 'tp' (Twisted Pair), 'aui' (Attachment Unit + * Interface), 'bnc' (Thin Ethernet) or 'mii' (Media Independent Interface. + * If the device supports only one port type, this setting is ignored. + **/ + g_object_class_install_property + (object_class, PROP_PORT, + g_param_spec_string (NM_SETTING_WIRED_PORT, + "Port", + "Specific port type to use if multiple the device " + "supports multiple attachment methods. One of " + "'tp' (Twisted Pair), 'aui' (Attachment Unit Interface), " + "'bnc' (Thin Ethernet) or 'mii' (Media Independent " + "Interface. If the device supports only one port " + "type, this setting is ignored.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWired:speed: + * + * If non-zero, request that the device use only the specified speed. + * In Mbit/s, ie 100 == 100Mbit/s. + **/ + g_object_class_install_property + (object_class, PROP_SPEED, + g_param_spec_uint (NM_SETTING_WIRED_SPEED, + "Speed", + "If non-zero, request that the device use only the " + "specified speed. In Mbit/s, ie 100 == 100Mbit/s.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWired:duplex: + * + * If specified, request that the device only use the specified duplex mode. + * Either 'half' or 'full'. + **/ + g_object_class_install_property + (object_class, PROP_DUPLEX, + g_param_spec_string (NM_SETTING_WIRED_DUPLEX, + "Duplex", + "If specified, request that the device only use the " + "specified duplex mode. Either 'half' or 'full'.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingEthernet:auto-negotiate: + * + * If TRUE, allow auto-negotiation of port speed and duplex mode. If FALSE, + * do not allow auto-negotiation, in which case the 'speed' and 'duplex' + * properties should be set. + **/ + g_object_class_install_property + (object_class, PROP_AUTO_NEGOTIATE, + g_param_spec_boolean (NM_SETTING_WIRED_AUTO_NEGOTIATE, + "AutoNegotiate", + "If TRUE, allow auto-negotiation of port speed and " + "duplex mode. If FALSE, do not allow auto-negotiation," + "in which case the 'speed' and 'duplex' properties " + "should be set.", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWired:mac-address: + * + * If specified, this connection will only apply to the ethernet device + * whose MAC address matches. This property does not change the MAC address + * of the device (known as MAC spoofing). + **/ + g_object_class_install_property + (object_class, PROP_MAC_ADDRESS, + _nm_param_spec_specialized (NM_SETTING_WIRED_MAC_ADDRESS, + "MAC Address", + "If specified, this connection will only apply to " + "the ethernet device whose MAC address matches. " + "This property does not change the MAC address " + "of the device (known as MAC spoofing).", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWired:mtu: + * + * If non-zero, only transmit packets of the specified size or smaller, + * breaking larger packets up into multiple Ethernet frames. + **/ + g_object_class_install_property + (object_class, PROP_MTU, + g_param_spec_uint (NM_SETTING_WIRED_MTU, + "MTU", + "If non-zero, only transmit packets of the specified " + "size or smaller, breaking larger packets up into " + "multiple Ethernet frames.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); +} + diff --git a/libnm-util/nm-setting-wired.h b/libnm-util/nm-setting-wired.h new file mode 100644 index 00000000..44127347 --- /dev/null +++ b/libnm-util/nm-setting-wired.h @@ -0,0 +1,88 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_WIRED_H +#define NM_SETTING_WIRED_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WIRED (nm_setting_wired_get_type ()) +#define NM_SETTING_WIRED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WIRED, NMSettingWired)) +#define NM_SETTING_WIRED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WIRED, NMSettingWiredClass)) +#define NM_IS_SETTING_WIRED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WIRED)) +#define NM_IS_SETTING_WIRED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_WIRED)) +#define NM_SETTING_WIRED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WIRED, NMSettingWiredClass)) + +#define NM_SETTING_WIRED_SETTING_NAME "802-3-ethernet" + +typedef enum +{ + NM_SETTING_WIRED_ERROR_UNKNOWN = 0, + NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRED_ERROR_MISSING_PROPERTY +} NMSettingWiredError; + +#define NM_TYPE_SETTING_WIRED_ERROR (nm_setting_wired_error_get_type ()) +GType nm_setting_wired_error_get_type (void); + +#define NM_SETTING_WIRED_ERROR nm_setting_wired_error_quark () +GQuark nm_setting_wired_error_quark (void); + +#define NM_SETTING_WIRED_PORT "port" +#define NM_SETTING_WIRED_SPEED "speed" +#define NM_SETTING_WIRED_DUPLEX "duplex" +#define NM_SETTING_WIRED_AUTO_NEGOTIATE "auto-negotiate" +#define NM_SETTING_WIRED_MAC_ADDRESS "mac-address" +#define NM_SETTING_WIRED_MTU "mtu" + +typedef struct { + NMSetting parent; +} NMSettingWired; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingWiredClass; + +GType nm_setting_wired_get_type (void); + +NMSetting *nm_setting_wired_new (void); +const char *nm_setting_wired_get_port (NMSettingWired *setting); +guint32 nm_setting_wired_get_speed (NMSettingWired *setting); +const char *nm_setting_wired_get_duplex (NMSettingWired *setting); +gboolean nm_setting_wired_get_auto_negotiate (NMSettingWired *setting); +const GByteArray *nm_setting_wired_get_mac_address (NMSettingWired *setting); +guint32 nm_setting_wired_get_mtu (NMSettingWired *setting); + +G_END_DECLS + +#endif /* NM_SETTING_WIRED_H */ diff --git a/libnm-util/nm-setting-wireless-security.c b/libnm-util/nm-setting-wireless-security.c new file mode 100644 index 00000000..678a6fad --- /dev/null +++ b/libnm-util/nm-setting-wireless-security.c @@ -0,0 +1,1208 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> +#include <ctype.h> +#include <dbus/dbus-glib.h> +#include "nm-setting-wireless-security.h" +#include "nm-setting-8021x.h" +#include "nm-param-spec-specialized.h" +#include "nm-utils.h" +#include "nm-dbus-glib-types.h" +#include "nm-utils-private.h" + +GQuark +nm_setting_wireless_security_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-wireless-security-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_wireless_security_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_WIRELESS_SECURITY_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_PROPERTY, "MissingProperty"), + /* The required 802.1x setting is missing */ + ENUM_ENTRY (NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING, "Missing8021xSetting"), + /* The LEAP authentication algorithm requires use of 802.1x key management. */ + ENUM_ENTRY (NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X, "LEAPRequires8021x"), + /* The LEAP authentication algorithm requires a username. */ + ENUM_ENTRY (NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME, "LEAPRequiresUsername"), + /* Shared Key authentication can only be used with WEP encryption. */ + ENUM_ENTRY (NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP, "SharedKeyRequiresWEP"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingWirelessSecurityError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING) + +#define NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurityPrivate)) + +typedef struct { + char *key_mgmt; + guint32 wep_tx_keyidx; + char *auth_alg; + GSList *proto; /* GSList of strings */ + GSList *pairwise; /* GSList of strings */ + GSList *group; /* GSList of strings */ + char *leap_username; + char *wep_key0; + char *wep_key1; + char *wep_key2; + char *wep_key3; + char *psk; + char *leap_password; + NMWepKeyType wep_key_type; +} NMSettingWirelessSecurityPrivate; + +enum { + PROP_0, + PROP_KEY_MGMT, + PROP_WEP_TX_KEYIDX, + PROP_AUTH_ALG, + PROP_PROTO, + PROP_PAIRWISE, + PROP_GROUP, + PROP_LEAP_USERNAME, + PROP_WEP_KEY0, + PROP_WEP_KEY1, + PROP_WEP_KEY2, + PROP_WEP_KEY3, + PROP_PSK, + PROP_LEAP_PASSWORD, + PROP_WEP_KEY_TYPE, + + LAST_PROP +}; + +NMSetting * +nm_setting_wireless_security_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIRELESS_SECURITY, NULL); +} + +const char * +nm_setting_wireless_security_get_key_mgmt (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->key_mgmt; +} + +guint32 +nm_setting_wireless_security_get_num_protos (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0); + + return g_slist_length (NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->proto); +} + +const char * +nm_setting_wireless_security_get_proto (NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->proto), NULL); + + return (const char *) g_slist_nth_data (priv->proto, i); +} + +gboolean +nm_setting_wireless_security_add_proto (NMSettingWirelessSecurity *setting, const char *proto) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE); + g_return_val_if_fail (proto != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + for (iter = priv->proto; iter; iter = g_slist_next (iter)) { + if (!strcmp (proto, (char *) iter->data)) + return FALSE; + } + + priv->proto = g_slist_append (priv->proto, g_ascii_strdown (proto, -1)); + return TRUE; +} + +void +nm_setting_wireless_security_remove_proto (NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + elt = g_slist_nth (priv->proto, i); + g_return_if_fail (elt != NULL); + + g_free (elt->data); + priv->proto = g_slist_delete_link (priv->proto, elt); +} + +void +nm_setting_wireless_security_clear_protos (NMSettingWirelessSecurity *setting) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + nm_utils_slist_free (priv->proto, g_free); + priv->proto = NULL; +} + +guint32 +nm_setting_wireless_security_get_num_pairwise (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0); + + return g_slist_length (NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->pairwise); +} + +const char * +nm_setting_wireless_security_get_pairwise (NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->pairwise), NULL); + + return (const char *) g_slist_nth_data (priv->pairwise, i); +} + +gboolean +nm_setting_wireless_security_add_pairwise (NMSettingWirelessSecurity *setting, const char *pairwise) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE); + g_return_val_if_fail (pairwise != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + for (iter = priv->pairwise; iter; iter = g_slist_next (iter)) { + if (!strcmp (pairwise, (char *) iter->data)) + return FALSE; + } + + priv->pairwise = g_slist_append (priv->pairwise, g_ascii_strdown (pairwise, -1)); + return TRUE; +} + +void +nm_setting_wireless_security_remove_pairwise (NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + elt = g_slist_nth (priv->pairwise, i); + g_return_if_fail (elt != NULL); + + g_free (elt->data); + priv->pairwise = g_slist_delete_link (priv->pairwise, elt); +} + +void +nm_setting_wireless_security_clear_pairwise (NMSettingWirelessSecurity *setting) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + nm_utils_slist_free (priv->pairwise, g_free); + priv->pairwise = NULL; +} + +guint32 +nm_setting_wireless_security_get_num_groups (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0); + + return g_slist_length (NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->group); +} + +const char * +nm_setting_wireless_security_get_group (NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + g_return_val_if_fail (i <= g_slist_length (priv->group), NULL); + + return (const char *) g_slist_nth_data (priv->group, i); +} + +gboolean +nm_setting_wireless_security_add_group (NMSettingWirelessSecurity *setting, const char *group) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList *iter; + + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE); + g_return_val_if_fail (group != NULL, FALSE); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + for (iter = priv->group; iter; iter = g_slist_next (iter)) { + if (!strcmp (group, (char *) iter->data)) + return FALSE; + } + + priv->group = g_slist_append (priv->group, g_ascii_strdown (group, -1)); + return TRUE; +} + +void +nm_setting_wireless_security_remove_group (NMSettingWirelessSecurity *setting, guint32 i) +{ + NMSettingWirelessSecurityPrivate *priv; + GSList *elt; + + g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + elt = g_slist_nth (priv->group, i); + g_return_if_fail (elt != NULL); + + g_free (elt->data); + priv->group = g_slist_delete_link (priv->group, elt); +} + +void +nm_setting_wireless_security_clear_groups (NMSettingWirelessSecurity *setting) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting)); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + nm_utils_slist_free (priv->group, g_free); + priv->group = NULL; +} + +const char * +nm_setting_wireless_security_get_psk (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->psk; +} + +const char * +nm_setting_wireless_security_get_leap_username (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->leap_username; +} + +const char * +nm_setting_wireless_security_get_leap_password (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->leap_password; +} + +const char * +nm_setting_wireless_security_get_wep_key (NMSettingWirelessSecurity *setting, guint32 idx) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL); + g_return_val_if_fail (idx < 4, NULL); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + if (idx == 0) + return priv->wep_key0; + else if (idx == 1) + return priv->wep_key1; + else if (idx == 2) + return priv->wep_key2; + else if (idx == 3) + return priv->wep_key3; + + g_assert_not_reached (); + return NULL; +} + +void +nm_setting_wireless_security_set_wep_key (NMSettingWirelessSecurity *setting, guint32 idx, const char *key) +{ + NMSettingWirelessSecurityPrivate *priv; + + g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting)); + g_return_if_fail (idx < 4); + + priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + switch (idx) { + case 0: + g_free (priv->wep_key0); + priv->wep_key0 = g_strdup (key); + break; + case 1: + g_free (priv->wep_key1); + priv->wep_key1 = g_strdup (key); + break; + case 2: + g_free (priv->wep_key2); + priv->wep_key2 = g_strdup (key); + break; + case 3: + g_free (priv->wep_key3); + priv->wep_key3 = g_strdup (key); + break; + default: + g_assert_not_reached (); + } +} + +guint32 +nm_setting_wireless_security_get_wep_tx_keyidx (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wep_tx_keyidx; +} + +const char * +nm_setting_wireless_security_get_auth_alg (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->auth_alg; +} + +NMWepKeyType +nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wep_key_type; +} + +static gboolean +verify_wep_key (const char *key, NMWepKeyType wep_type) +{ + int keylen, i; + + if (!key) + return FALSE; + + keylen = strlen (key); + if (wep_type == NM_WEP_KEY_TYPE_KEY || NM_WEP_KEY_TYPE_UNKNOWN) { + if (keylen == 10 || keylen == 26) { + /* Hex key */ + for (i = 0; i < keylen; i++) { + if (!isxdigit (key[i])) + return FALSE; + } + } else if (keylen == 5 || keylen == 13) { + /* ASCII key */ + for (i = 0; i < keylen; i++) { + if (!isascii (key[i])) + return FALSE; + } + } else + return FALSE; + + } else if (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE) { + if (!keylen || keylen > 64) + return FALSE; + } + + return TRUE; +} + +static gboolean +verify_wpa_psk (const char *psk) +{ + int psklen, i; + + if (!psk) + return FALSE; + + psklen = strlen (psk); + if (psklen < 8 || psklen > 64) + return FALSE; + + if (psklen == 64) { + /* Hex PSK */ + for (i = 0; i < psklen; i++) { + if (!isxdigit (psk[i])) + return FALSE; + } + } + + return TRUE; +} + + +static GPtrArray * +need_secrets (NMSetting *setting) +{ + NMSettingWirelessSecurity *self = NM_SETTING_WIRELESS_SECURITY (setting); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self); + GPtrArray *secrets; + + secrets = g_ptr_array_sized_new (4); + if (!secrets) { + g_warning ("Not enough memory to create required secrets array."); + return NULL; + } + + g_assert (priv->key_mgmt); + + /* Static WEP */ + if (strcmp (priv->key_mgmt, "none") == 0) { + if ((priv->wep_tx_keyidx == 0) && !verify_wep_key (priv->wep_key0, priv->wep_key_type)) { + g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0); + return secrets; + } + if ((priv->wep_tx_keyidx == 1) && !verify_wep_key (priv->wep_key1, priv->wep_key_type)) { + g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1); + return secrets; + } + if ((priv->wep_tx_keyidx == 2) && !verify_wep_key (priv->wep_key2, priv->wep_key_type)) { + g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2); + return secrets; + } + if ((priv->wep_tx_keyidx == 3) && !verify_wep_key (priv->wep_key3, priv->wep_key_type)) { + g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3); + return secrets; + } + goto no_secrets; + } + + /* WPA-PSK infrastructure and adhoc */ + if ( (strcmp (priv->key_mgmt, "wpa-none") == 0) + || (strcmp (priv->key_mgmt, "wpa-psk") == 0)) { + if (!verify_wpa_psk (priv->psk)) { + g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_PSK); + return secrets; + } + goto no_secrets; + } + + /* LEAP */ + if ( priv->auth_alg + && !strcmp (priv->auth_alg, "leap") + && !strcmp (priv->key_mgmt, "ieee8021x")) { + if (!priv->leap_password || !strlen (priv->leap_password)) { + g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD); + return secrets; + } + goto no_secrets; + } + + if ( (strcmp (priv->key_mgmt, "ieee8021x") == 0) + || (strcmp (priv->key_mgmt, "wpa-eap") == 0)) { + /* Let caller check the 802.1x setting for secrets */ + goto no_secrets; + } + + g_assert_not_reached (); + return secrets; + +no_secrets: + if (secrets) + g_ptr_array_free (secrets, TRUE); + return NULL; +} + +static gint +find_setting_by_name (gconstpointer a, gconstpointer b) +{ + NMSetting *setting = NM_SETTING (a); + const char *str = (const char *) b; + + return strcmp (nm_setting_get_name (setting), str); +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingWirelessSecurity *self = NM_SETTING_WIRELESS_SECURITY (setting); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self); + const char *valid_key_mgmt[] = { "none", "ieee8021x", "wpa-none", "wpa-psk", "wpa-eap", NULL }; + const char *valid_auth_algs[] = { "open", "shared", "leap", NULL }; + const char *valid_protos[] = { "wpa", "rsn", NULL }; + const char *valid_pairwise[] = { "wep40", "wep104", "tkip", "ccmp", NULL }; + const char *valid_groups[] = { "wep40", "wep104", "tkip", "ccmp", NULL }; + + if (!priv->key_mgmt) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); + return FALSE; + } + + if (!_nm_utils_string_in_list (priv->key_mgmt, valid_key_mgmt)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT); + return FALSE; + } + + if (priv->auth_alg && !strcmp (priv->auth_alg, "leap")) { + /* LEAP must use ieee8021x key management */ + if (strcmp (priv->key_mgmt, "ieee8021x")) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + return FALSE; + } + if (!priv->leap_username) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME, + NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME); + return FALSE; + } + if (priv->leap_password && !strlen (priv->leap_password)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD); + return FALSE; + } + } else { + if ( (strcmp (priv->key_mgmt, "ieee8021x") == 0) + || (strcmp (priv->key_mgmt, "wpa-eap") == 0)) { + /* Need an 802.1x setting too */ + if (!g_slist_find_custom (all_settings, NM_SETTING_802_1X_SETTING_NAME, find_setting_by_name)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING, + NULL); + return FALSE; + } + } + } + + if (priv->leap_username && !strlen (priv->leap_username)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME); + return FALSE; + } + + if (priv->wep_tx_keyidx > 3) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX); + return FALSE; + } + + if (priv->wep_key_type > NM_WEP_KEY_TYPE_LAST) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE); + return FALSE; + } + + if (priv->wep_key0 && !verify_wep_key (priv->wep_key0, priv->wep_key_type)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY0); + return FALSE; + } + if (priv->wep_key1 && !verify_wep_key (priv->wep_key1, priv->wep_key_type)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY1); + return FALSE; + } + if (priv->wep_key2 && !verify_wep_key (priv->wep_key2, priv->wep_key_type)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY2); + return FALSE; + } + if (priv->wep_key3 && !verify_wep_key (priv->wep_key3, priv->wep_key_type)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY3); + return FALSE; + } + + if (priv->auth_alg && !_nm_utils_string_in_list (priv->auth_alg, valid_auth_algs)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + return FALSE; + } + + if (priv->psk && !verify_wpa_psk (priv->psk)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_PSK); + return FALSE; + } + + if (priv->proto && !_nm_utils_string_slist_validate (priv->proto, valid_protos)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_PROTO); + return FALSE; + } + + if (priv->pairwise) { + const char *wpa_none[] = { "wpa-none", NULL }; + + /* For ad-hoc connections, pairwise must be "none" */ + if (_nm_utils_string_in_list (priv->key_mgmt, wpa_none)) { + GSList *iter; + gboolean found = FALSE; + + for (iter = priv->pairwise; iter; iter = g_slist_next (iter)) { + if (!strcmp ((char *) iter->data, "none")) { + found = TRUE; + break; + } + } + + /* pairwise cipher list didn't contain "none", which is invalid + * for WPA adhoc connections. + */ + if (!found) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_PAIRWISE); + return FALSE; + } + } else if (!_nm_utils_string_slist_validate (priv->pairwise, valid_pairwise)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_PAIRWISE); + return FALSE; + } + } + + if (priv->group && !_nm_utils_string_slist_validate (priv->group, valid_groups)) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_GROUP); + return FALSE; + } + + /* Shared Key auth can only be used with WEP */ + if (priv->auth_alg && !strcmp (priv->auth_alg, "shared")) { + if (priv->key_mgmt && strcmp (priv->key_mgmt, "none")) { + g_set_error (error, + NM_SETTING_WIRELESS_SECURITY_ERROR, + NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG); + return FALSE; + } + } + + return TRUE; +} + +static void +nm_setting_wireless_security_init (NMSettingWirelessSecurity *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingWirelessSecurity *self = NM_SETTING_WIRELESS_SECURITY (object); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self); + + /* Strings first. g_free() already checks for NULLs so we don't have to */ + + g_free (priv->key_mgmt); + g_free (priv->auth_alg); + g_free (priv->leap_username); + g_free (priv->wep_key0); + g_free (priv->wep_key1); + g_free (priv->wep_key2); + g_free (priv->wep_key3); + g_free (priv->psk); + g_free (priv->leap_password); + + nm_utils_slist_free (priv->proto, g_free); + nm_utils_slist_free (priv->pairwise, g_free); + nm_utils_slist_free (priv->group, g_free); + + G_OBJECT_CLASS (nm_setting_wireless_security_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingWirelessSecurity *setting = NM_SETTING_WIRELESS_SECURITY (object); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + const char *str; + + switch (prop_id) { + case PROP_KEY_MGMT: + g_free (priv->key_mgmt); + str = g_value_get_string (value); + priv->key_mgmt = str ? g_ascii_strdown (str, -1) : NULL; + break; + case PROP_WEP_TX_KEYIDX: + priv->wep_tx_keyidx = g_value_get_uint (value); + break; + case PROP_AUTH_ALG: + g_free (priv->auth_alg); + str = g_value_get_string (value); + priv->auth_alg = str ? g_ascii_strdown (str, -1) : NULL; + break; + case PROP_PROTO: + nm_utils_slist_free (priv->proto, g_free); + priv->proto = g_value_dup_boxed (value); + break; + case PROP_PAIRWISE: + nm_utils_slist_free (priv->pairwise, g_free); + priv->pairwise = g_value_dup_boxed (value); + break; + case PROP_GROUP: + nm_utils_slist_free (priv->group, g_free); + priv->group = g_value_dup_boxed (value); + break; + case PROP_LEAP_USERNAME: + g_free (priv->leap_username); + priv->leap_username = g_value_dup_string (value); + break; + case PROP_WEP_KEY0: + nm_setting_wireless_security_set_wep_key (setting, 0, g_value_get_string (value)); + break; + case PROP_WEP_KEY1: + nm_setting_wireless_security_set_wep_key (setting, 1, g_value_get_string (value)); + break; + case PROP_WEP_KEY2: + nm_setting_wireless_security_set_wep_key (setting, 2, g_value_get_string (value)); + break; + case PROP_WEP_KEY3: + nm_setting_wireless_security_set_wep_key (setting, 3, g_value_get_string (value)); + break; + case PROP_PSK: + g_free (priv->psk); + priv->psk = g_value_dup_string (value); + break; + case PROP_LEAP_PASSWORD: + g_free (priv->leap_password); + priv->leap_password = g_value_dup_string (value); + break; + case PROP_WEP_KEY_TYPE: + priv->wep_key_type = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingWirelessSecurity *setting = NM_SETTING_WIRELESS_SECURITY (object); + NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_KEY_MGMT: + g_value_set_string (value, priv->key_mgmt); + break; + case PROP_WEP_TX_KEYIDX: + g_value_set_uint (value, priv->wep_tx_keyidx); + break; + case PROP_AUTH_ALG: + g_value_set_string (value, priv->auth_alg); + break; + case PROP_PROTO: + g_value_set_boxed (value, priv->proto); + break; + case PROP_PAIRWISE: + g_value_set_boxed (value, priv->pairwise); + break; + case PROP_GROUP: + g_value_set_boxed (value, priv->group); + break; + case PROP_LEAP_USERNAME: + g_value_set_string (value, priv->leap_username); + break; + case PROP_WEP_KEY0: + g_value_set_string (value, priv->wep_key0); + break; + case PROP_WEP_KEY1: + g_value_set_string (value, priv->wep_key1); + break; + case PROP_WEP_KEY2: + g_value_set_string (value, priv->wep_key2); + break; + case PROP_WEP_KEY3: + g_value_set_string (value, priv->wep_key3); + break; + case PROP_PSK: + g_value_set_string (value, priv->psk); + break; + case PROP_LEAP_PASSWORD: + g_value_set_string (value, priv->leap_password); + break; + case PROP_WEP_KEY_TYPE: + g_value_set_uint (value, priv->wep_key_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingWirelessSecurityPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + parent_class->verify = verify; + parent_class->need_secrets = need_secrets; + + /* Properties */ + /** + * NMSettingWirelessSecurity:key-mgmt: + * + * Key management used for the connection. One of 'none' (WEP), 'ieee8021x' + * (Dynamic WEP), 'wpa-none' (Ad-Hoc WPA-PSK), 'wpa-psk' (infrastructure + * WPA-PSK), or 'wpa-eap' (WPA-Enterprise). This property must be set for + * any WiFi connection that uses security. + **/ + g_object_class_install_property + (object_class, PROP_KEY_MGMT, + g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + "Key management", + "Key management used for the connection. One of " + "'none' (WEP), 'ieee8021x' (Dynamic WEP), 'wpa-none' " + "(WPA-PSK Ad-Hoc), 'wpa-psk' (infrastructure WPA-PSK), " + "or 'wpa-eap' (WPA-Enterprise). This property must " + "be set for any WiFi connection that uses security.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_REQUIRED)); + + /** + * NMSettingWirelessSecurity:wep-tx-keyidx: + * + * When static WEP is used (ie, key-mgmt = 'none') and a non-default WEP key + * index is used by the AP, put that WEP key index here. Valid values are 0 + * (default key) through 3. Note that some consumer access points (like the + * Linksys WRT54G) number the keys 1 - 4. + **/ + g_object_class_install_property + (object_class, PROP_WEP_TX_KEYIDX, + g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, + "WEP TX key index", + "When static WEP is used (ie, key-mgmt = 'none') and a " + "non-default WEP key index is used by the AP, put that " + "WEP key index here. Valid values are 0 (default key) " + "through 3. Note that some consumer access points " + "(like the Linksys WRT54G) number the keys 1 - 4.", + 0, 3, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWirelessSecurity:auth-alg: + * + * When WEP is used (ie, key-mgmt = 'none' or 'ieee8021x') indicate the + * 802.11 authentication algorithm required by the AP here. One of 'open' + * for Open System, 'shared' for Shared Key, or 'leap' for Cisco LEAP. + * When using Cisco LEAP (ie, key-mgmt = 'ieee8021x' and auth-alg = 'leap') + * the 'leap-username' and 'leap-password' properties must be specified. + **/ + g_object_class_install_property + (object_class, PROP_AUTH_ALG, + g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, + "AuthAlg", + "When WEP is used (ie, key-mgmt = 'none' or " + "'ieee8021x') indicate the 802.11 authentication " + "algorithm required by the AP here. One of 'open' for " + "Open System, 'shared' for Shared Key, or 'leap' for " + "Cisco LEAP. When using Cisco LEAP (ie, key-mgmt = " + "'ieee8021x' and auth-alg = 'leap') the 'leap-username' " + "and 'leap-password' properties must be specified.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWirelessSecurity:proto: + * + * List of strings specifying the allowed WPA protocol versions to use. + * Each element may be one 'wpa' (allow WPA) or 'rsn' (allow WPA2/RSN). If + * not specified, both WPA and RSN connections are allowed. + **/ + g_object_class_install_property + (object_class, PROP_PROTO, + _nm_param_spec_specialized (NM_SETTING_WIRELESS_SECURITY_PROTO, + "Proto", + "List of strings specifying the allowed WPA " + "protocol versions to use. Each element may be " + "one 'wpa' (allow WPA) or 'rsn' (allow " + "WPA2/RSN). If not specified, both WPA and RSN " + "connections are allowed.", + DBUS_TYPE_G_LIST_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWirelessSecurity:pairwise: + * + * If specified, will only connect to WPA networks that provide the + * specified pairwise encryption capabilities. Each element may be one of + * 'wep40', 'wep104', 'tkip', or 'ccmp'. + **/ + g_object_class_install_property + (object_class, PROP_PAIRWISE, + _nm_param_spec_specialized (NM_SETTING_WIRELESS_SECURITY_PAIRWISE, + "Pairwise", + "If specified, will only connect to WPA networks " + "that provide the specified pairwise encryption " + "capabilities. Each element may be one of 'wep40', " + "'wep104', 'tkip', or 'ccmp'.", + DBUS_TYPE_G_LIST_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWirelessSecurity:group: + * + * If specified, will only connect to WPA networks that provide the + * specified group/multicast encryption capabilities. Each element may be + * one of 'wep40', 'wep104', 'tkip', or 'ccmp'. + **/ + g_object_class_install_property + (object_class, PROP_GROUP, + _nm_param_spec_specialized (NM_SETTING_WIRELESS_SECURITY_GROUP, + "Group", + "If specified, will only connect to WPA networks " + "that provide the specified group/multicast " + "encryption capabilities. Each element may be " + "one of 'wep40', 'wep104', 'tkip', or 'ccmp'.", + DBUS_TYPE_G_LIST_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWirelessSecurity:leap-username: + * + * The login username for legacy LEAP connections (ie, key-mgmt = + * 'ieee8021x' and auth-alg = 'leap'). + **/ + g_object_class_install_property + (object_class, PROP_LEAP_USERNAME, + g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, + "LEAP Username", + "The login username for legacy LEAP connections " + "(ie, key-mgmt = 'ieee8021x' and auth-alg = 'leap').", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWirelessSecurity:wep-key0: + * + * Index 0 WEP key. This is the WEP key used in most networks. See the + * 'wep-key-type' property for a description of how this key is interpreted. + **/ + g_object_class_install_property + (object_class, PROP_WEP_KEY0, + g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, + "WEP key0", + "Index 0 WEP key. This is the WEP key used in most " + "networks. See the 'wep-key-type' property for a " + "description of how this key is interpreted.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSettingWirelessSecurity:wep-key1: + * + * Index 1 WEP key. This WEP index is not used by most networks. See the + * 'wep-key-type' property for a description of how this key is interpreted. + **/ + g_object_class_install_property + (object_class, PROP_WEP_KEY1, + g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, + "WEP key1", + "Index 1 WEP key. This WEP index is not used by most " + "networks. See the 'wep-key-type' property for a " + "description of how this key is interpreted.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSettingWirelessSecurity:wep-key2: + * + * Index 2 WEP key. This WEP index is not used by most networks. See the + * 'wep-key-type' property for a description of how this key is interpreted. + **/ + g_object_class_install_property + (object_class, PROP_WEP_KEY2, + g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, + "WEP key2", + "Index 2 WEP key. This WEP index is not used by most " + "networks. See the 'wep-key-type' property for a " + "description of how this key is interpreted.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSettingWirelessSecurity:wep-key3: + * + * Index 3 WEP key. This WEP index is not used by most networks. See the + * 'wep-key-type' property for a description of how this key is interpreted. + **/ + g_object_class_install_property + (object_class, PROP_WEP_KEY3, + g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, + "WEP key3", + "Index 3 WEP key. This WEP index is not used by most " + "networks. See the 'wep-key-type' property for a " + "description of how this key is interpreted.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSettingWirelessSecurity:psk: + * + * Pre-Shared-Key for WPA networks. If the key is 64-characters long, it + * must contain only hexadecimal characters and is interpreted as a + * hexadecimal WPA key. Otherwise, the key must be between 8 and 63 ASCII + * characters (as specified in the 802.11i standard) and is interpreted as + * a WPA passphrase, and is hashed to derive the actual WPA-PSK used when + * connecting to the WiFi network. + **/ + g_object_class_install_property + (object_class, PROP_PSK, + g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_PSK, + "PSK", + "Pre-Shared-Key for WPA networks. If the key is " + "64-characters long, it must contain only hexadecimal " + "characters and is interpreted as a hexadecimal WPA " + "key. Otherwise, the key must be between 8 and 63 " + "ASCII characters (as specified in the 802.11i standard) " + "and is interpreted as a WPA passphrase, and is hashed " + "to derive the actual WPA-PSK used when connecting to " + "the WiFi network.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSettingWirelessSecurity:leap-password: + * + * The login password for legacy LEAP connections (ie, key-mgmt = + * 'ieee8021x' and auth-alg = 'leap'). + **/ + g_object_class_install_property + (object_class, PROP_LEAP_PASSWORD, + g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, + "LEAP Password", + "The login password for legacy LEAP connections " + "(ie, key-mgmt = 'ieee8021x' and auth-alg = 'leap').", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET)); + + /** + * NMSettingWirelessSecurity:wep-key-type: + * + * Controls the interpretation of WEP keys. Allowed values are 1 (interpret + * WEP keys as hexadecimal or ASCII keys) or 2 (interpret WEP keys as WEP + * Passphrases). If set to 1 and the keys are hexadecimal, they must be + * either 10 or 26 characters in length. If set to 1 and the keys are + * ASCII keys, they must be either 5 or 13 characters in length. If set to + * 2, the passphrase is hashed using the de-facto MD5 method to derive the + * actual WEP key. + **/ + g_object_class_install_property + (object_class, PROP_WEP_KEY_TYPE, + g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, + "WEP Key Type", + "Controls the interpretation of WEP keys. Allowed values " + "are 1 (interpret WEP keys as hexadecimal or ASCII keys) " + "or 2 (interpret WEP keys as WEP Passphrases). If set to " + "1 and the keys are hexadecimal, they must be either 10 or " + "26 characters in length. If set to 1 and the keys are " + "ASCII keys, they must be either 5 or 13 characters in " + "length. If set to 2, the passphrase is hashed using " + " the de-facto MD5 method to derive the actual WEP key.", + NM_WEP_KEY_TYPE_UNKNOWN, + NM_WEP_KEY_TYPE_LAST, + NM_WEP_KEY_TYPE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); +} diff --git a/libnm-util/nm-setting-wireless-security.h b/libnm-util/nm-setting-wireless-security.h new file mode 100644 index 00000000..90d971b2 --- /dev/null +++ b/libnm-util/nm-setting-wireless-security.h @@ -0,0 +1,133 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_WIRELESS_SECURITY_H +#define NM_SETTING_WIRELESS_SECURITY_H + +#include <nm-setting.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_get_type ()) +#define NM_SETTING_WIRELESS_SECURITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurity)) +#define NM_SETTING_WIRELESS_SECURITY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurityClass)) +#define NM_IS_SETTING_WIRELESS_SECURITY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WIRELESS_SECURITY)) +#define NM_IS_SETTING_WIRELESS_SECURITY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_WIRELESS_SECURITY)) +#define NM_SETTING_WIRELESS_SECURITY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurityClass)) + +#define NM_SETTING_WIRELESS_SECURITY_SETTING_NAME "802-11-wireless-security" + +typedef enum +{ + NM_SETTING_WIRELESS_SECURITY_ERROR_UNKNOWN = 0, + NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_PROPERTY, + NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING, + NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X, + NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME, + NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP +} NMSettingWirelessSecurityError; + +#define NM_TYPE_SETTING_WIRELESS_SECURITY_ERROR (nm_setting_wireless_security_error_get_type ()) +GType nm_setting_wireless_security_error_get_type (void); + +#define NM_SETTING_WIRELESS_SECURITY_ERROR nm_setting_wireless_security_error_quark () +GQuark nm_setting_wireless_security_error_quark (void); + +typedef enum { + NM_WEP_KEY_TYPE_UNKNOWN = 0, + NM_WEP_KEY_TYPE_KEY = 1, /* Hex or ASCII */ + NM_WEP_KEY_TYPE_PASSPHRASE = 2, /* 104/128-bit Passphrase */ + + NM_WEP_KEY_TYPE_LAST = NM_WEP_KEY_TYPE_PASSPHRASE +} NMWepKeyType; + +#define NM_SETTING_WIRELESS_SECURITY_KEY_MGMT "key-mgmt" +#define NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX "wep-tx-keyidx" +#define NM_SETTING_WIRELESS_SECURITY_AUTH_ALG "auth-alg" +#define NM_SETTING_WIRELESS_SECURITY_PROTO "proto" +#define NM_SETTING_WIRELESS_SECURITY_PAIRWISE "pairwise" +#define NM_SETTING_WIRELESS_SECURITY_GROUP "group" +#define NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME "leap-username" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY0 "wep-key0" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY1 "wep-key1" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY2 "wep-key2" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY3 "wep-key3" +#define NM_SETTING_WIRELESS_SECURITY_PSK "psk" +#define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD "leap-password" +#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE "wep-key-type" + +typedef struct { + NMSetting parent; +} NMSettingWirelessSecurity; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingWirelessSecurityClass; + +GType nm_setting_wireless_security_get_type (void); + +NMSetting * nm_setting_wireless_security_new (void); + +const char *nm_setting_wireless_security_get_key_mgmt (NMSettingWirelessSecurity *setting); + +guint32 nm_setting_wireless_security_get_num_protos (NMSettingWirelessSecurity *setting); +const char *nm_setting_wireless_security_get_proto (NMSettingWirelessSecurity *setting, guint32 i); +gboolean nm_setting_wireless_security_add_proto (NMSettingWirelessSecurity *setting, const char *proto); +void nm_setting_wireless_security_remove_proto (NMSettingWirelessSecurity *setting, guint32 i); +void nm_setting_wireless_security_clear_protos (NMSettingWirelessSecurity *setting); + +guint32 nm_setting_wireless_security_get_num_pairwise (NMSettingWirelessSecurity *setting); +const char *nm_setting_wireless_security_get_pairwise (NMSettingWirelessSecurity *setting, guint32 i); +gboolean nm_setting_wireless_security_add_pairwise (NMSettingWirelessSecurity *setting, const char *pairwise); +void nm_setting_wireless_security_remove_pairwise (NMSettingWirelessSecurity *setting, guint32 i); +void nm_setting_wireless_security_clear_pairwise (NMSettingWirelessSecurity *setting); + +guint32 nm_setting_wireless_security_get_num_groups (NMSettingWirelessSecurity *setting); +const char *nm_setting_wireless_security_get_group (NMSettingWirelessSecurity *setting, guint32 i); +gboolean nm_setting_wireless_security_add_group (NMSettingWirelessSecurity *setting, const char *group); +void nm_setting_wireless_security_remove_group (NMSettingWirelessSecurity *setting, guint32 i); +void nm_setting_wireless_security_clear_groups (NMSettingWirelessSecurity *setting); + +const char *nm_setting_wireless_security_get_psk (NMSettingWirelessSecurity *setting); + +const char *nm_setting_wireless_security_get_leap_username (NMSettingWirelessSecurity *setting); +const char *nm_setting_wireless_security_get_leap_password (NMSettingWirelessSecurity *setting); + +const char *nm_setting_wireless_security_get_wep_key (NMSettingWirelessSecurity *setting, guint32 idx); +void nm_setting_wireless_security_set_wep_key (NMSettingWirelessSecurity *setting, guint32 idx, const char *key); +guint32 nm_setting_wireless_security_get_wep_tx_keyidx (NMSettingWirelessSecurity *setting); +const char *nm_setting_wireless_security_get_auth_alg (NMSettingWirelessSecurity *setting); +NMWepKeyType nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSecurity *setting); + +G_END_DECLS + +#endif /* NM_SETTING_WIRELESS_SECURITY_H */ diff --git a/libnm-util/nm-setting-wireless.c b/libnm-util/nm-setting-wireless.c new file mode 100644 index 00000000..9213429c --- /dev/null +++ b/libnm-util/nm-setting-wireless.c @@ -0,0 +1,909 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> +#include <netinet/ether.h> +#include <dbus/dbus-glib.h> + +#include "wireless-helper.h" + +#include "NetworkManager.h" +#include "nm-setting-wireless.h" +#include "nm-param-spec-specialized.h" +#include "nm-utils.h" +#include "nm-dbus-glib-types.h" +#include "nm-utils-private.h" + +GQuark +nm_setting_wireless_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-wireless-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_wireless_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_WIRELESS_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_WIRELESS_ERROR_MISSING_PROPERTY, "MissingProperty"), + /* The required security setting is missing */ + ENUM_ENTRY (NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING, "MissingSecuritySetting"), + /* The 'channel' property requires a valid 'band' */ + ENUM_ENTRY (NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND, "ChannelRequiresBand"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingWirelessError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING) + +#define NM_SETTING_WIRELESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessPrivate)) + +typedef struct { + GByteArray *ssid; + char *mode; + char *band; + guint32 channel; + GByteArray *bssid; + guint32 rate; + guint32 tx_power; + GByteArray *mac_address; + guint32 mtu; + GSList *seen_bssids; + char *security; +} NMSettingWirelessPrivate; + +enum { + PROP_0, + PROP_SSID, + PROP_MODE, + PROP_BAND, + PROP_CHANNEL, + PROP_BSSID, + PROP_RATE, + PROP_TX_POWER, + PROP_MAC_ADDRESS, + PROP_MTU, + PROP_SEEN_BSSIDS, + PROP_SEC, + + LAST_PROP +}; + +static gboolean +match_cipher (const char *cipher, + const char *expected, + guint32 wpa_flags, + guint32 rsn_flags, + guint32 flag) +{ + if (strcmp (cipher, expected) != 0) + return FALSE; + + if (!(wpa_flags & flag) && !(rsn_flags & flag)) + return FALSE; + + return TRUE; +} + +gboolean +nm_setting_wireless_ap_security_compatible (NMSettingWireless *s_wireless, + NMSettingWirelessSecurity *s_wireless_sec, + guint32 ap_flags, + guint32 ap_wpa, + guint32 ap_rsn, + guint32 ap_mode) +{ + NMSettingWirelessPrivate *priv; + const char *key_mgmt = NULL, *cipher; + guint32 num, i; + gboolean found = FALSE; + + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (s_wireless), FALSE); + + priv = NM_SETTING_WIRELESS_GET_PRIVATE (s_wireless); + + if (!priv->security) { + if ( (ap_flags & NM_802_11_AP_FLAGS_PRIVACY) + || (ap_wpa != NM_802_11_AP_SEC_NONE) + || (ap_rsn != NM_802_11_AP_SEC_NONE)) + return FALSE; + return TRUE; + } + + if (strcmp (priv->security, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) != 0) + return FALSE; + + if (s_wireless_sec) + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec); + + if (s_wireless_sec == NULL || !key_mgmt) + return FALSE; + + /* Static WEP */ + if (!strcmp (key_mgmt, "none")) { + if ( !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY) + || (ap_wpa != NM_802_11_AP_SEC_NONE) + || (ap_rsn != NM_802_11_AP_SEC_NONE)) + return FALSE; + return TRUE; + } + + /* Adhoc WPA */ + if (!strcmp (key_mgmt, "wpa-none")) { + if (ap_mode != NM_802_11_MODE_ADHOC) + return FALSE; + // FIXME: validate ciphers if the BSSID actually puts WPA/RSN IE in + // it's beacon + return TRUE; + } + + /* Stuff after this point requires infrastructure */ + if (ap_mode != NM_802_11_MODE_INFRA) + return FALSE; + + /* Dynamic WEP or LEAP */ + if (!strcmp (key_mgmt, "ieee8021x")) { + if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) + return FALSE; + + /* If the AP is advertising a WPA IE, make sure it supports WEP ciphers */ + if (ap_wpa != NM_802_11_AP_SEC_NONE) { + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + + /* quick check; can't use AP if it doesn't support at least one + * WEP cipher in both pairwise and group suites. + */ + if ( !(ap_wpa & (NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104)) + || !(ap_wpa & (NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104))) + return FALSE; + + /* Match at least one pairwise cipher with AP's capability if the + * wireless-security setting explicitly lists pairwise ciphers + */ + num = nm_setting_wireless_security_get_num_pairwise (s_wireless_sec); + for (i = 0, found = FALSE; i < num; i++) { + cipher = nm_setting_wireless_security_get_pairwise (s_wireless_sec, i); + if ((found = match_cipher (cipher, "wep40", ap_wpa, ap_wpa, NM_802_11_AP_SEC_PAIR_WEP40))) + break; + if ((found = match_cipher (cipher, "wep104", ap_wpa, ap_wpa, NM_802_11_AP_SEC_PAIR_WEP104))) + break; + } + if (!found && num) + return FALSE; + + /* Match at least one group cipher with AP's capability if the + * wireless-security setting explicitly lists group ciphers + */ + num = nm_setting_wireless_security_get_num_groups (s_wireless_sec); + for (i = 0, found = FALSE; i < num; i++) { + cipher = nm_setting_wireless_security_get_group (s_wireless_sec, i); + if ((found = match_cipher (cipher, "wep40", ap_wpa, ap_wpa, NM_802_11_AP_SEC_GROUP_WEP40))) + break; + if ((found = match_cipher (cipher, "wep104", ap_wpa, ap_wpa, NM_802_11_AP_SEC_GROUP_WEP104))) + break; + } + if (!found && num) + return FALSE; + } + return TRUE; + } + + /* WPA[2]-PSK and WPA[2] Enterprise */ + if ( !strcmp (key_mgmt, "wpa-psk") + || !strcmp (key_mgmt, "wpa-eap")) { + + if (!strcmp (key_mgmt, "wpa-psk")) { + if ( !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) + && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK)) + return FALSE; + } else if (!strcmp (key_mgmt, "wpa-eap")) { + if ( !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + } + + // FIXME: should handle WPA and RSN separately here to ensure that + // if the Connection only uses WPA we don't match a cipher against + // the AP's RSN IE instead + + /* Match at least one pairwise cipher with AP's capability if the + * wireless-security setting explicitly lists pairwise ciphers + */ + num = nm_setting_wireless_security_get_num_pairwise (s_wireless_sec); + for (i = 0, found = FALSE; i < num; i++) { + cipher = nm_setting_wireless_security_get_pairwise (s_wireless_sec, i); + if ((found = match_cipher (cipher, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_TKIP))) + break; + if ((found = match_cipher (cipher, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_CCMP))) + break; + } + if (!found && num) + return FALSE; + + /* Match at least one group cipher with AP's capability if the + * wireless-security setting explicitly lists group ciphers + */ + num = nm_setting_wireless_security_get_num_groups (s_wireless_sec); + for (i = 0, found = FALSE; i < num; i++) { + cipher = nm_setting_wireless_security_get_group (s_wireless_sec, i); + + if ((found = match_cipher (cipher, "wep40", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP40))) + break; + if ((found = match_cipher (cipher, "wep104", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP104))) + break; + if ((found = match_cipher (cipher, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_TKIP))) + break; + if ((found = match_cipher (cipher, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_CCMP))) + break; + } + if (!found && num) + return FALSE; + + return TRUE; + } + + return FALSE; +} + +NMSetting * +nm_setting_wireless_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIRELESS, NULL); +} + +const GByteArray * +nm_setting_wireless_get_ssid (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->ssid; +} + +const char * +nm_setting_wireless_get_mode (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mode; +} + +const char * +nm_setting_wireless_get_band (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->band; +} + +guint32 +nm_setting_wireless_get_channel (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->channel; +} + +const GByteArray * +nm_setting_wireless_get_bssid (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->bssid; +} + +guint32 +nm_setting_wireless_get_rate (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->rate; +} + +guint32 +nm_setting_wireless_get_tx_power (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->tx_power; +} + +const GByteArray * +nm_setting_wireless_get_mac_address (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mac_address; +} + +guint32 +nm_setting_wireless_get_mtu (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mtu; +} + +const char * +nm_setting_wireless_get_security (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL); + + return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->security; +} + +gboolean +nm_setting_wireless_add_seen_bssid (NMSettingWireless *setting, + const char *bssid) +{ + NMSettingWirelessPrivate *priv; + char *lower_bssid; + GSList *iter; + gboolean found = FALSE; + + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE); + g_return_val_if_fail (bssid != NULL, FALSE); + + lower_bssid = g_ascii_strdown (bssid, -1); + if (!lower_bssid) + return FALSE; + + priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting); + + for (iter = priv->seen_bssids; iter; iter = iter->next) { + if (!strcmp ((char *) iter->data, lower_bssid)) { + found = TRUE; + break; + } + } + + if (!found) + priv->seen_bssids = g_slist_prepend (priv->seen_bssids, lower_bssid); + else + g_free (lower_bssid); + + return !found; +} + +guint32 +nm_setting_wireless_get_num_seen_bssids (NMSettingWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0); + + return g_slist_length (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->seen_bssids); +} + +const char * +nm_setting_wireless_get_seen_bssid (NMSettingWireless *setting, + guint32 i) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL); + + return (const char *) g_slist_nth_data (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->seen_bssids, i); +} + +static gint +find_setting_by_name (gconstpointer a, gconstpointer b) +{ + NMSetting *setting = NM_SETTING (a); + const char *str = (const char *) b; + + return strcmp (nm_setting_get_name (setting), str); +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting); + const char *valid_modes[] = { "infrastructure", "adhoc", NULL }; + const char *valid_bands[] = { "a", "bg", NULL }; + GSList *iter; + + if (!priv->ssid) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_MISSING_PROPERTY, + NM_SETTING_WIRELESS_SSID); + return FALSE; + } + + if (!priv->ssid->len || priv->ssid->len > 32) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SSID); + return FALSE; + } + + if (priv->mode && !_nm_utils_string_in_list (priv->mode, valid_modes)) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_MODE); + return FALSE; + } + + if (priv->band && !_nm_utils_string_in_list (priv->band, valid_bands)) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_BAND); + return FALSE; + } + + if (priv->channel && !priv->band) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND, + NM_SETTING_WIRELESS_BAND); + return FALSE; + } + + if (priv->channel) { + if (!strcmp (priv->band, "a")) { + int i; + int valid_channels[] = { 7, 8, 9, 11, 12, 16, 34, 36, 40, 44, 48, + 52, 56, 60, 64, 100, 104, 108, 112, 116, + 120, 124, 128, 132, 136, 140, 149, 153, + 157, 161, 165, 183, 184, 185, 187, 188, + 192, 196, 0 }; + + for (i = 0; valid_channels[i]; i++) { + if (priv->channel == valid_channels[i]) + break; + } + + if (valid_channels[i] == 0) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_CHANNEL); + return FALSE; + } + } else if (!strcmp (priv->band, "bg") && priv->channel > 14) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_CHANNEL); + return FALSE; + } + } + + if (priv->bssid && priv->bssid->len != ETH_ALEN) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_BSSID); + return FALSE; + } + + if (priv->mac_address && priv->mac_address->len != ETH_ALEN) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_MAC_ADDRESS); + return FALSE; + } + + for (iter = priv->seen_bssids; iter; iter = iter->next) { + struct ether_addr addr; + + if (!ether_aton_r (iter->data, &addr)) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_SEEN_BSSIDS); + return FALSE; + } + } + + if ( priv->security + && !g_slist_find_custom (all_settings, priv->security, find_setting_by_name)) { + g_set_error (error, + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING, + NULL); + return FALSE; + } + + return TRUE; +} + +static void +nm_setting_wireless_init (NMSettingWireless *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_WIRELESS_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (object); + + g_free (priv->mode); + g_free (priv->band); + g_free (priv->security); + + if (priv->ssid) + g_byte_array_free (priv->ssid, TRUE); + if (priv->bssid) + g_byte_array_free (priv->bssid, TRUE); + if (priv->mac_address) + g_byte_array_free (priv->mac_address, TRUE); + + nm_utils_slist_free (priv->seen_bssids, g_free); + + G_OBJECT_CLASS (nm_setting_wireless_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_SSID: + if (priv->ssid) + g_byte_array_free (priv->ssid, TRUE); + priv->ssid = g_value_dup_boxed (value); + break; + case PROP_MODE: + g_free (priv->mode); + priv->mode = g_value_dup_string (value); + break; + case PROP_BAND: + g_free (priv->band); + priv->band = g_value_dup_string (value); + break; + case PROP_CHANNEL: + priv->channel = g_value_get_uint (value); + break; + case PROP_BSSID: + if (priv->bssid) + g_byte_array_free (priv->bssid, TRUE); + priv->bssid = g_value_dup_boxed (value); + break; + case PROP_RATE: + priv->rate = g_value_get_uint (value); + break; + case PROP_TX_POWER: + priv->tx_power = g_value_get_uint (value); + break; + case PROP_MAC_ADDRESS: + if (priv->mac_address) + g_byte_array_free (priv->mac_address, TRUE); + priv->mac_address = g_value_dup_boxed (value); + break; + case PROP_MTU: + priv->mtu = g_value_get_uint (value); + break; + case PROP_SEEN_BSSIDS: + nm_utils_slist_free (priv->seen_bssids, g_free); + priv->seen_bssids = g_value_dup_boxed (value); + break; + case PROP_SEC: + g_free (priv->security); + priv->security = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingWireless *setting = NM_SETTING_WIRELESS (object); + + switch (prop_id) { + case PROP_SSID: + g_value_set_boxed (value, nm_setting_wireless_get_ssid (setting)); + break; + case PROP_MODE: + g_value_set_string (value, nm_setting_wireless_get_mode (setting)); + break; + case PROP_BAND: + g_value_set_string (value, nm_setting_wireless_get_band (setting)); + break; + case PROP_CHANNEL: + g_value_set_uint (value, nm_setting_wireless_get_channel (setting)); + break; + case PROP_BSSID: + g_value_set_boxed (value, nm_setting_wireless_get_bssid (setting)); + break; + case PROP_RATE: + g_value_set_uint (value, nm_setting_wireless_get_rate (setting)); + break; + case PROP_TX_POWER: + g_value_set_uint (value, nm_setting_wireless_get_tx_power (setting)); + break; + case PROP_MAC_ADDRESS: + g_value_set_boxed (value, nm_setting_wireless_get_mac_address (setting)); + break; + case PROP_MTU: + g_value_set_uint (value, nm_setting_wireless_get_mtu (setting)); + break; + case PROP_SEEN_BSSIDS: + g_value_set_boxed (value, NM_SETTING_WIRELESS_GET_PRIVATE (setting)->seen_bssids); + break; + case PROP_SEC: + g_value_set_string (value, nm_setting_wireless_get_security (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingWirelessPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ + /** + * NMSettingWireless:ssid: + * + * SSID of the WiFi network. + **/ + g_object_class_install_property + (object_class, PROP_SSID, + _nm_param_spec_specialized (NM_SETTING_WIRELESS_SSID, + "SSID", + "SSID of the WiFi network. Must be specified.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWireless:mode: + * + * WiFi network mode; one of 'infrastructure' or 'adhoc'. If blank, + * infrastructure is assumed. + **/ + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_string (NM_SETTING_WIRELESS_MODE, + "Mode", + "WiFi network mode; one of 'infrastructure' or " + "'adhoc'. If blank, infrastructure is assumed.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWireless:band: + * + * 802.11 frequency band of the network. One of 'a' for 5GHz 802.11a or + * 'bg' for 2.4GHz 802.11. This will lock associations to the WiFi network + * to the specific band, i.e. if 'a' is specified, the device will not + * associate with the same network in the 2.4GHz band even if the network's + * settings are compatible. This setting depends on specific driver + * capability and may not work with all drivers. + **/ + g_object_class_install_property + (object_class, PROP_BAND, + g_param_spec_string (NM_SETTING_WIRELESS_BAND, + "Band", + "802.11 frequency band of the network. One of 'a' " + "for 5GHz 802.11a or 'bg' for 2.4GHz 802.11. This " + "will lock associations to the WiFi network to the " + "specific band, i.e. if 'a' is specified, the device " + "will not associate with the same network in the " + "2.4GHz band even if the network's settings are " + "compatible. This setting depends on specific driver " + "capability and may not work with all drivers.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWireless:channel: + * + * Wireless channel to use for the WiFi connection. The device will only + * join (or create for Ad-Hoc networks) a WiFi network on the specified + * channel. Because channel numbers overlap between bands, this property + * also requires the 'band' property to be set. + **/ + g_object_class_install_property + (object_class, PROP_CHANNEL, + g_param_spec_uint (NM_SETTING_WIRELESS_CHANNEL, + "Channel", + "Wireless channel to use for the WiFi connection. The " + "device will only join (or create for Ad-Hoc networks) " + "a WiFi network on the specified channel. Because " + "channel numbers overlap between bands, this property " + "also requires the 'band' property to be set.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWireless:bssid: + * + * If specified, directs the device to only associate with the given access + * point. This capability is highly driver dependent and not supported by + * all devices. Note: this property does not control the BSSID used when + * creating an Ad-Hoc network and is unlikely to in the future. + **/ + g_object_class_install_property + (object_class, PROP_BSSID, + _nm_param_spec_specialized (NM_SETTING_WIRELESS_BSSID, + "BSSID", + "If specified, directs the device to only associate " + "with the given access point. This capability is " + "highly driver dependent and not supported by all " + "devices. Note: this property does not control " + "the BSSID used when creating an Ad-Hoc network " + "and is unlikely to in the future.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWireless:rate: + * + * If non-zero, directs the device to only use the specified bitrate for + * communication with the access point. Units are in Kb/s, ie 5500 = 5.5 + * Mbit/s. This property is highly driver dependent and not all devices + * support setting a static bitrate. + **/ + g_object_class_install_property + (object_class, PROP_RATE, + g_param_spec_uint (NM_SETTING_WIRELESS_RATE, + "Rate", + "If non-zero, directs the device to only use the " + "specified bitrate for communication with the access " + "point. Units are in Kb/s, ie 5500 = 5.5 Mbit/s. This " + "property is highly driver dependent and not all devices " + "support setting a static bitrate.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingWireless:tx-power: + * + * If non-zero, directs the device to use the specified transmit power. + * Units are dBm. This property is highly driver dependent and not all + * devices support setting a static transmit power. + **/ + g_object_class_install_property + (object_class, PROP_TX_POWER, + g_param_spec_uint (NM_SETTING_WIRELESS_TX_POWER, + "TX Power", + "If non-zero, directs the device to use the specified " + "transmit power. Units are dBm. This property is highly " + "driver dependent and not all devices support setting a " + "static transmit power.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingWireless:mac-address: + * + * If specified, this connection will only apply to the WiFi device + * whose MAC address matches. This property does not change the MAC address + * of the device (known as MAC spoofing). + **/ + g_object_class_install_property + (object_class, PROP_MAC_ADDRESS, + _nm_param_spec_specialized (NM_SETTING_WIRELESS_MAC_ADDRESS, + "MAC Address", + "If specified, this connection will only apply to " + "the WiFi device whose MAC address matches. " + "This property does not change the MAC address " + "of the device (known as MAC spoofing).", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWireless:seen-bssids: + * + * A list of BSSIDs (each BSSID formatted as a MAC address like + * '00:11:22:33:44:55') that have been detected as part of the WiFI network. + * The settings service will usually populate this property by periodically + * asking NetworkManager what the device's current AP is while connected + * to the network (or monitoring the device's 'active-ap' property) and + * adding the current AP'sBSSID to this list. This list helps NetworkManager + * find hidden APs by matching up scan results with the BSSIDs in this list. + **/ + g_object_class_install_property + (object_class, PROP_SEEN_BSSIDS, + _nm_param_spec_specialized (NM_SETTING_WIRELESS_SEEN_BSSIDS, + "Seen BSSIDS", + "A list of BSSIDs (each BSSID formatted as a MAC " + "address like '00:11:22:33:44:55') that have been " + "detected as part of the WiFI network. The " + "settings service will usually populate this " + "property by periodically asking NetworkManager " + "what the device's current AP is while connected " + "to the network (or monitoring the device's " + "'active-ap' property) and adding the current AP's " + "BSSID to this list. This list helps NetworkManager " + "find hidden APs by matching up scan results with " + "the BSSIDs in this list.", + DBUS_TYPE_G_LIST_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingWireless:mtu: + * + * If non-zero, only transmit packets of the specified size or smaller, + * breaking larger packets up into multiple Ethernet frames. + **/ + g_object_class_install_property + (object_class, PROP_MTU, + g_param_spec_uint (NM_SETTING_WIRELESS_MTU, + "MTU", + "If non-zero, only transmit packets of the specified " + "size or smaller, breaking larger packets up into " + "multiple Ethernet frames.", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingWireless:security: + * + * If the wireless connection has any security restrictions, like 802.1x, + * WEP, or WPA, set this property to '802-11-wireless-security' and ensure + * the connection contains a valid 802-11-wireless-security setting. + **/ + g_object_class_install_property + (object_class, PROP_SEC, + g_param_spec_string (NM_SETTING_WIRELESS_SEC, + "Security", + "If the wireless connection has any security " + "restrictions, like 802.1x, WEP, or WPA, set this " + "property to '" NM_SETTING_WIRELESS_SECURITY_SETTING_NAME "' " + "and ensure the connection contains a valid " + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME " setting.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); +} diff --git a/libnm-util/nm-setting-wireless.h b/libnm-util/nm-setting-wireless.h new file mode 100644 index 00000000..da2ea5b6 --- /dev/null +++ b/libnm-util/nm-setting-wireless.h @@ -0,0 +1,115 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_WIRELESS_H +#define NM_SETTING_WIRELESS_H + +#include <nm-setting.h> +#include <nm-setting-wireless-security.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WIRELESS (nm_setting_wireless_get_type ()) +#define NM_SETTING_WIRELESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WIRELESS, NMSettingWireless)) +#define NM_SETTING_WIRELESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessClass)) +#define NM_IS_SETTING_WIRELESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WIRELESS)) +#define NM_IS_SETTING_WIRELESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_WIRELESS)) +#define NM_SETTING_WIRELESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessClass)) + +#define NM_SETTING_WIRELESS_SETTING_NAME "802-11-wireless" + +typedef enum +{ + NM_SETTING_WIRELESS_ERROR_UNKNOWN = 0, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_ERROR_MISSING_PROPERTY, + NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING, + NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND +} NMSettingWirelessError; + +#define NM_TYPE_SETTING_WIRELESS_ERROR (nm_setting_wireless_error_get_type ()) +GType nm_setting_wireless_error_get_type (void); + +#define NM_SETTING_WIRELESS_ERROR nm_setting_wireless_error_quark () +GQuark nm_setting_wireless_error_quark (void); + +#define NM_SETTING_WIRELESS_SSID "ssid" +#define NM_SETTING_WIRELESS_MODE "mode" +#define NM_SETTING_WIRELESS_BAND "band" +#define NM_SETTING_WIRELESS_CHANNEL "channel" +#define NM_SETTING_WIRELESS_BSSID "bssid" +#define NM_SETTING_WIRELESS_RATE "rate" +#define NM_SETTING_WIRELESS_TX_POWER "tx-power" +#define NM_SETTING_WIRELESS_MAC_ADDRESS "mac-address" +#define NM_SETTING_WIRELESS_MTU "mtu" +#define NM_SETTING_WIRELESS_SEEN_BSSIDS "seen-bssids" +#define NM_SETTING_WIRELESS_SEC "security" + +typedef struct { + NMSetting parent; +} NMSettingWireless; + +typedef struct { + NMSettingClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingWirelessClass; + +GType nm_setting_wireless_get_type (void); + +NMSetting *nm_setting_wireless_new (void); + +const GByteArray *nm_setting_wireless_get_ssid (NMSettingWireless *setting); +const char *nm_setting_wireless_get_mode (NMSettingWireless *setting); +const char *nm_setting_wireless_get_band (NMSettingWireless *setting); +guint32 nm_setting_wireless_get_channel (NMSettingWireless *setting); +const GByteArray *nm_setting_wireless_get_bssid (NMSettingWireless *setting); +guint32 nm_setting_wireless_get_rate (NMSettingWireless *setting); +guint32 nm_setting_wireless_get_tx_power (NMSettingWireless *setting); +const GByteArray *nm_setting_wireless_get_mac_address (NMSettingWireless *setting); +guint32 nm_setting_wireless_get_mtu (NMSettingWireless *setting); +const char *nm_setting_wireless_get_security (NMSettingWireless *setting); + +gboolean nm_setting_wireless_add_seen_bssid (NMSettingWireless *setting, + const char *bssid); + +guint32 nm_setting_wireless_get_num_seen_bssids (NMSettingWireless *setting); +const char *nm_setting_wireless_get_seen_bssid (NMSettingWireless *setting, + guint32 i); + +gboolean nm_setting_wireless_ap_security_compatible (NMSettingWireless *s_wireless, + NMSettingWirelessSecurity *s_wireless_sec, + guint32 ap_flags, + guint32 ap_wpa, + guint32 ap_rsn, + guint32 ap_mode); + +G_END_DECLS + +#endif /* NM_SETTING_WIRELESS_H */ diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c new file mode 100644 index 00000000..06994c73 --- /dev/null +++ b/libnm-util/nm-setting.c @@ -0,0 +1,752 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#include <string.h> + +#include "nm-setting.h" +#include "nm-setting-connection.h" +#include "nm-utils.h" + +/** + * SECTION:nm-setting + * @short_description: Describes related configuration information + * @include: nm-setting.h + * + * Each #NMSetting contains properties that describe configuration that applies + * to a specific network layer (like IPv4 or IPv6 configuration) or device type + * (like Ethernet, or WiFi). A collection of individual settings together + * make up an #NMConnection. Each property is strongly typed and usually has + * a number of allowed values. See each #NMSetting subclass for a description + * of properties and allowed values. + */ + +/** + * nm_setting_error_quark: + * + * Registers an error quark for #NMSetting if necessary. + * + * Returns: the error quark used for NMSetting errors. + **/ +GQuark +nm_setting_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + ENUM_ENTRY (NM_SETTING_ERROR_UNKNOWN, "UnknownError"), + ENUM_ENTRY (NM_SETTING_ERROR_PROPERTY_NOT_FOUND, "PropertyNotFound"), + ENUM_ENTRY (NM_SETTING_ERROR_PROPERTY_NOT_SECRET, "PropertyNotSecret"), + ENUM_ENTRY (NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, "PropertyTypeMismatch"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingError", values); + } + return etype; +} + +G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT) + +#define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate)) + +typedef struct { + char *name; +} NMSettingPrivate; + +enum { + PROP_0, + PROP_NAME, + + PROP_LAST +}; + +static void +destroy_gvalue (gpointer data) +{ + GValue *value = (GValue *) data; + + g_value_unset (value); + g_slice_free (GValue, value); +} + +/** + * nm_setting_to_hash: + * @setting: the #NMSetting + * + * Converts the #NMSetting into a #GHashTable mapping each setting property + * name to a GValue describing that property, suitable for marshalling over + * D-Bus or serializing. The mapping is string:GValue. + * + * Returns: a new #GHashTable describing the setting's properties + **/ +GHashTable * +nm_setting_to_hash (NMSetting *setting) +{ + GHashTable *hash; + GParamSpec **property_specs; + guint n_property_specs; + guint i; + + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + + property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); + if (!property_specs) { + g_warning ("%s: couldn't find property specs for object of type '%s'", + __func__, g_type_name (G_OBJECT_TYPE (setting))); + return NULL; + } + + hash = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + destroy_gvalue); + + for (i = 0; i < n_property_specs; i++) { + GParamSpec *prop_spec = property_specs[i]; + + if (prop_spec->flags & NM_SETTING_PARAM_SERIALIZE) { + GValue *value; + + value = g_slice_new0 (GValue); + g_value_init (value, prop_spec->value_type); + g_object_get_property (G_OBJECT (setting), prop_spec->name, value); + + /* Don't serialize values with default values */ + if (!g_param_value_defaults (prop_spec, value)) + g_hash_table_insert (hash, g_strdup (prop_spec->name), value); + else + destroy_gvalue (value); + } + } + + g_free (property_specs); + + return hash; +} + +typedef struct { + GObjectClass *class; + guint n_params; + GParameter *params; +} NMSettingFromHashInfo; + +static void +one_property_cb (gpointer key, gpointer val, gpointer user_data) +{ + const char *prop_name = (char *) key; + GValue *src_value = (GValue *) val; + NMSettingFromHashInfo *info = (NMSettingFromHashInfo *) user_data; + GValue *dst_value = &info->params[info->n_params].value; + GParamSpec *param_spec; + + param_spec = g_object_class_find_property (info->class, prop_name); + if (!param_spec || !(param_spec->flags & NM_SETTING_PARAM_SERIALIZE)) { + /* Oh, we're so nice and only warn, maybe it should be a fatal error? */ + nm_warning ("Ignoring invalid property '%s'", prop_name); + return; + } + + g_value_init (dst_value, G_VALUE_TYPE (src_value)); + if (g_value_transform (src_value, dst_value)) { + info->params[info->n_params].name = prop_name; + info->n_params++; + } else { + nm_warning ("Ignoring property '%s' with invalid type (%s)", + prop_name, G_VALUE_TYPE_NAME (src_value)); + g_value_unset (dst_value); + } +} + +/** + * nm_setting_new_from_hash: + * @setting_type: the #NMSetting type which the hash contains properties for + * @hash: the #GHashTable containing a string:GValue mapping of properties + * that apply to the setting + * + * Creates a new #NMSetting object and populates that object with the properties + * contained in the hash table, using each hash key as the property to set, + * and each hash value as the value to set that property to. Setting properties + * are strongly typed, thus the GValue type of the hash value must be correct. + * See the documentation on each #NMSetting object subclass for the correct + * property names and value types. + * + * Returns: a new #NMSetting object populated with the properties from the + * hash table, or NULL on failure + **/ +NMSetting * +nm_setting_new_from_hash (GType setting_type, + GHashTable *hash) +{ + NMSetting *setting; + NMSettingFromHashInfo info; + int i; + + g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL); + g_return_val_if_fail (hash != NULL, NULL); + + info.class = g_type_class_ref (setting_type); + info.n_params = 0; + info.params = g_new0 (GParameter, g_hash_table_size (hash)); + + g_hash_table_foreach (hash, one_property_cb, &info); + + setting = (NMSetting *) g_object_newv (setting_type, info.n_params, info.params); + + for (i = 0; i < info.n_params; i++) { + GValue *v = &info.params[i].value; + g_value_unset (v); + } + + g_free (info.params); + g_type_class_unref (info.class); + + return setting; +} + +static void +duplicate_setting (NMSetting *setting, + const char *name, + const GValue *value, + GParamFlags flags, + gpointer user_data) +{ + if (flags & G_PARAM_WRITABLE) + g_object_set_property (G_OBJECT (user_data), name, value); +} + +/** + * nm_setting_duplicate: + * @setting: the #NMSetting to duplicate + * + * Duplicates a #NMSetting. + * + * Returns: a new #NMSetting containing the same properties and values as the + * source #NMSetting + **/ +NMSetting * +nm_setting_duplicate (NMSetting *setting) +{ + GObject *dup; + + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + + dup = g_object_new (G_OBJECT_TYPE (setting), NULL); + + g_object_freeze_notify (dup); + nm_setting_enumerate_values (setting, duplicate_setting, dup); + g_object_thaw_notify (dup); + + return NM_SETTING (dup); +} + +/** + * nm_setting_get_name: + * @setting: the #NMSetting + * + * Returns the type name of the #NMSetting object + * + * Returns: a string containing the type name of the #NMSetting object, + * like 'ppp' or 'wireless' or 'wired'. + **/ +const char * +nm_setting_get_name (NMSetting *setting) +{ + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + + return NM_SETTING_GET_PRIVATE (setting)->name; +} + +/** + * nm_setting_verify: + * @setting: the #NMSetting to verify + * @all_settings: a #GSList of all settings in the connection from which @setting + * came + * @error: location to store error, or %NULL + * + * Validates the setting. Each setting's properties have allowed values, and + * some are dependent on other values (hence the need for @all_settings). The + * returned #GError contains information about which property of the setting + * failed validation, and in what way that property failed validation. + * + * Returns: %TRUE if the setting is valid, %FALSE if it is not + **/ +gboolean +nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); + if (error) + g_return_val_if_fail (*error == NULL, FALSE); + + if (NM_SETTING_GET_CLASS (setting)->verify) + return NM_SETTING_GET_CLASS (setting)->verify (setting, all_settings, error); + + return TRUE; +} + +/** + * nm_setting_compare: + * @a: a #NMSetting + * @b: a second #NMSetting to compare with the first + * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT + * + * Compares two #NMSetting objects for similarity, with comparison behavior + * modified by a set of flags. See the documentation for #NMSettingCompareFlags + * for a description of each flag's behavior. + * + * Returns: %TRUE if the comparison succeeds, %FALSE if it does not + **/ +gboolean +nm_setting_compare (NMSetting *a, + NMSetting *b, + NMSettingCompareFlags flags) +{ + GParamSpec **property_specs; + guint n_property_specs; + gint different; + guint i; + + g_return_val_if_fail (NM_IS_SETTING (a), FALSE); + g_return_val_if_fail (NM_IS_SETTING (b), FALSE); + + /* First check that both have the same type */ + if (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b)) + return FALSE; + + /* And now all properties */ + property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs); + different = FALSE; + + for (i = 0; i < n_property_specs && !different; i++) { + GParamSpec *prop_spec = property_specs[i]; + GValue value1 = { 0 }; + GValue value2 = { 0 }; + + /* Fuzzy compare ignores secrets and properties defined with the + * FUZZY_IGNORE flag + */ + if ( (flags & NM_SETTING_COMPARE_FLAG_FUZZY) + && (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET))) + continue; + + if ((flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) && (prop_spec->flags & NM_SETTING_PARAM_SECRET)) + continue; + + if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID) + && !strcmp (nm_setting_get_name (a), NM_SETTING_CONNECTION_SETTING_NAME) + && !strcmp (prop_spec->name, NM_SETTING_CONNECTION_ID)) + continue; + + g_value_init (&value1, prop_spec->value_type); + g_object_get_property (G_OBJECT (a), prop_spec->name, &value1); + + g_value_init (&value2, prop_spec->value_type); + g_object_get_property (G_OBJECT (b), prop_spec->name, &value2); + + different = g_param_values_cmp (prop_spec, &value1, &value2); + + g_value_unset (&value1); + g_value_unset (&value2); + } + + g_free (property_specs); + + return different == 0 ? TRUE : FALSE; +} + +/** + * nm_setting_enumerate_values: + * @setting: the #NMSetting + * @func: user-supplied function called for each property of the setting + * @user_data: user data passed to @func at each invocation + * + * Iterates over each property of the #NMSetting object, calling the supplied + * user function for each property. + **/ +void +nm_setting_enumerate_values (NMSetting *setting, + NMSettingValueIterFn func, + gpointer user_data) +{ + GParamSpec **property_specs; + guint n_property_specs; + int i; + + g_return_if_fail (NM_IS_SETTING (setting)); + g_return_if_fail (func != NULL); + + property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); + for (i = 0; i < n_property_specs; i++) { + GParamSpec *prop_spec = property_specs[i]; + GValue value = { 0 }; + + g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec)); + g_object_get_property (G_OBJECT (setting), prop_spec->name, &value); + func (setting, prop_spec->name, &value, prop_spec->flags, user_data); + g_value_unset (&value); + } + + g_free (property_specs); +} + +/** + * nm_setting_clear_secrets: + * @setting: the #NMSetting + * + * Resets and clears any secrets in the setting. Secrets should be added to the + * setting only when needed, and cleared immediately after use to prevent + * leakage of information. + **/ +void +nm_setting_clear_secrets (NMSetting *setting) +{ + GParamSpec **property_specs; + guint n_property_specs; + guint i; + + g_return_if_fail (NM_IS_SETTING (setting)); + + property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); + + for (i = 0; i < n_property_specs; i++) { + GParamSpec *prop_spec = property_specs[i]; + GValue value = { 0 }; + + if (prop_spec->flags & NM_SETTING_PARAM_SECRET) { + g_value_init (&value, prop_spec->value_type); + g_param_value_set_default (prop_spec, &value); + g_object_set_property (G_OBJECT (setting), prop_spec->name, &value); + g_value_unset (&value); + } + } + + g_free (property_specs); +} + +/** + * nm_setting_need_secrets: + * @setting: the #NMSetting + * + * Returns an array of property names for each secret which may be required + * to make a successful connection. The returned hints are only intended as a + * guide to what secrets may be required, because in some circumstances, there + * is no way to conclusively determine exactly which secrets are needed. + * + * Returns: a #GPtrArray containing the property names of secrets of the + * #NMSetting which may be required; the caller owns the array + * and must free the each array element with g_free(), as well as the array + * itself with g_ptr_array_free() + **/ +GPtrArray * +nm_setting_need_secrets (NMSetting *setting) +{ + GPtrArray *secrets = NULL; + + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + + if (NM_SETTING_GET_CLASS (setting)->need_secrets) + secrets = NM_SETTING_GET_CLASS (setting)->need_secrets (setting); + + return secrets; +} + +typedef struct { + NMSetting *setting; + GError **error; +} UpdateSecretsInfo; + +static gboolean +update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error) +{ + GParamSpec *prop_spec; + GValue transformed_value = { 0 }; + gboolean success = FALSE; + + prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key); + if (!prop_spec) { + g_set_error (error, + NM_SETTING_ERROR, + NM_SETTING_ERROR_PROPERTY_NOT_FOUND, + "%s", key); + return FALSE; + } + + if (!(prop_spec->flags & NM_SETTING_PARAM_SECRET)) { + g_set_error (error, + NM_SETTING_ERROR, + NM_SETTING_ERROR_PROPERTY_NOT_SECRET, + "%s", key); + return FALSE; + } + + if (g_value_type_compatible (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (prop_spec))) { + g_object_set_property (G_OBJECT (setting), prop_spec->name, value); + success = TRUE; + } else if (g_value_transform (value, &transformed_value)) { + g_object_set_property (G_OBJECT (setting), prop_spec->name, &transformed_value); + g_value_unset (&transformed_value); + success = TRUE; + } else { + g_set_error (error, + NM_SETTING_ERROR, + NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, + "%s", key); + } + return success; +} + +static void +update_one_cb (gpointer key, gpointer val, gpointer user_data) +{ + UpdateSecretsInfo *info = user_data; + const char *secret_key = (const char *) key; + GValue *secret_value = (GValue *) val; + + if (*(info->error) == NULL) + NM_SETTING_GET_CLASS (info->setting)->update_one_secret (info->setting, secret_key, secret_value, info->error); +} + +/** + * nm_setting_update_secrets: + * @setting: the #NMSetting + * @secrets: a #GHashTable mapping string:#GValue of setting property names and + * secrets + * @error: location to store error, or %NULL + * + * Update the setting's secrets, given a hash table of secrets intended for that + * setting (deserialized from D-Bus for example). + * + * Returns: %TRUE if the secrets were successfully updated and the connection + * is valid, %FALSE on failure or if the setting was never added to the connection + **/ +gboolean +nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets, GError **error) +{ + UpdateSecretsInfo *info; + gboolean success; + + g_return_val_if_fail (setting != NULL, FALSE); + g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); + g_return_val_if_fail (secrets != NULL, FALSE); + if (error) + g_return_val_if_fail (*error == NULL, FALSE); + + info = g_malloc0 (sizeof (UpdateSecretsInfo)); + info->setting = setting; + info->error = error; + g_hash_table_foreach (secrets, update_one_cb, info); + success = *(info->error) ? FALSE : TRUE; + g_free (info); + + return success; +} + +/** + * nm_setting_to_string: + * @setting: the #NMSetting + * + * Convert the setting into a string. For debugging purposes ONLY, should NOT + * be used for serialization of the setting, or machine-parsed in any way. The + * output format is not guaranteed to be stable and may change at any time. + * + * Returns: an allocated string containing a textual representation of the + * setting's properties and values (including secrets!), which the caller should + * free with g_free() + **/ +char * +nm_setting_to_string (NMSetting *setting) +{ + GString *string; + GParamSpec **property_specs; + guint n_property_specs; + guint i; + + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + + property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); + if (!property_specs) + return NULL; + + string = g_string_new (nm_setting_get_name (setting)); + g_string_append_c (string, '\n'); + + for (i = 0; i < n_property_specs; i++) { + GParamSpec *prop_spec = property_specs[i]; + GValue value = { 0 }; + char *value_str; + gboolean is_serializable; + gboolean is_default; + + g_value_init (&value, prop_spec->value_type); + g_object_get_property (G_OBJECT (setting), prop_spec->name, &value); + + value_str = g_strdup_value_contents (&value); + g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str); + g_free (value_str); + + is_serializable = prop_spec->flags & NM_SETTING_PARAM_SERIALIZE; + is_default = g_param_value_defaults (prop_spec, &value); + + if (is_serializable || is_default) { + g_string_append (string, " ("); + + if (is_serializable) + g_string_append_c (string, 's'); + if (is_default) + g_string_append_c (string, 'd'); + + g_string_append_c (string, ')'); + } + + g_string_append_c (string, '\n'); + } + + g_free (property_specs); + g_string_append_c (string, '\n'); + + return g_string_free (string, FALSE); +} + +/*****************************************************************************/ + +static void +nm_setting_init (NMSetting *setting) +{ +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMSettingPrivate *priv; + + object = G_OBJECT_CLASS (nm_setting_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + priv = NM_SETTING_GET_PRIVATE (object); + if (!priv->name) { + nm_warning ("Setting name is not set."); + g_object_unref (object); + object = NULL; + } + + return object; +} + +static void +finalize (GObject *object) +{ + NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object); + + g_free (priv->name); + + G_OBJECT_CLASS (nm_setting_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_NAME: + g_free (priv->name); + priv->name = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSetting *setting = NM_SETTING (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, nm_setting_get_name (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_class_init (NMSettingClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingPrivate)); + + /* virtual methods */ + object_class->constructor = constructor; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + setting_class->update_one_secret = update_one_secret; + + /* Properties */ + + /** + * NMSetting:name: + * + * The setting's name, which uniquely identifies the setting within the + * connection. Each setting type has a name unique to that type, for + * example 'ppp' or 'wireless' or 'wired'. + **/ + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_SETTING_NAME, + "Name", + "The setting's name; these names are defined by the " + "specification and cannot be changed after the object " + "has been created. Each setting class has a name, and " + "all objects of that class share the same name.", + NULL, + G_PARAM_READWRITE)); +} + diff --git a/libnm-util/nm-setting.h b/libnm-util/nm-setting.h new file mode 100644 index 00000000..de5657ee --- /dev/null +++ b/libnm-util/nm-setting.h @@ -0,0 +1,179 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2008 Novell, Inc. + */ + +#ifndef NM_SETTING_H +#define NM_SETTING_H + +#include <glib.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING (nm_setting_get_type ()) +#define NM_SETTING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING, NMSetting)) +#define NM_SETTING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING, NMSettingClass)) +#define NM_IS_SETTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING)) +#define NM_IS_SETTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING)) +#define NM_SETTING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING, NMSettingClass)) + +/** + * NMSettingError: + * @NM_SETTING_ERROR_UNKNOWN: unknown or unclassified error + * @NM_SETTING_ERROR_PROPERTY_NOT_FOUND: a property required by the operation + * was not found; for example, an attempt to update an invalid secret + * @NM_SETTING_ERROR_PROPERTY_NOT_SECRET: an operation which requires a secret + * was attempted on a non-secret property + * @NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH: the operation requires a property + * of a specific type, or the value couldn't be transformed to the same type + * as the property being acted upon + * + * Describes errors that may result from operations involving a #NMSetting. + * + **/ +typedef enum +{ + NM_SETTING_ERROR_UNKNOWN = 0, + NM_SETTING_ERROR_PROPERTY_NOT_FOUND, + NM_SETTING_ERROR_PROPERTY_NOT_SECRET, + NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH +} NMSettingError; + +#define NM_TYPE_SETTING_ERROR (nm_setting_error_get_type ()) +GType nm_setting_error_get_type (void); + +#define NM_SETTING_ERROR nm_setting_error_quark () +GQuark nm_setting_error_quark (void); + + +/* The property of the #NMSetting should be serialized */ +#define NM_SETTING_PARAM_SERIALIZE (1 << (0 + G_PARAM_USER_SHIFT)) + +/* The property of the #NMSetting is required for the setting to be valid */ +#define NM_SETTING_PARAM_REQUIRED (1 << (1 + G_PARAM_USER_SHIFT)) + +/* The property of the #NMSetting is a secret */ +#define NM_SETTING_PARAM_SECRET (1 << (2 + G_PARAM_USER_SHIFT)) + +/* The property of the #NMSetting should be ignored during comparisons that + * use the %NM_SETTING_COMPARE_FLAG_FUZZY flag. + */ +#define NM_SETTING_PARAM_FUZZY_IGNORE (1 << (3 + G_PARAM_USER_SHIFT)) + +#define NM_SETTING_NAME "name" + +/** + * NMSetting: + * + * The NMSetting struct contains only private data. + * It should only be accessed through the functions described below. + */ +typedef struct { + GObject parent; +} NMSetting; + +typedef struct { + GObjectClass parent; + + /* Virtual functions */ + gboolean (*verify) (NMSetting *setting, + GSList *all_settings, + GError **error); + + GPtrArray *(*need_secrets) (NMSetting *setting); + + gboolean (*update_one_secret) (NMSetting *setting, + const char *key, + GValue *value, + GError **error); + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); +} NMSettingClass; + +typedef void (*NMSettingValueIterFn) (NMSetting *setting, + const char *key, + const GValue *value, + GParamFlags flags, + gpointer user_data); + + +GType nm_setting_get_type (void); + +GHashTable *nm_setting_to_hash (NMSetting *setting); +NMSetting *nm_setting_new_from_hash (GType setting_type, + GHashTable *hash); + +NMSetting *nm_setting_duplicate (NMSetting *setting); + +const char *nm_setting_get_name (NMSetting *setting); + +gboolean nm_setting_verify (NMSetting *setting, + GSList *all_settings, + GError **error); + +/** + * NMSettingCompareFlags: + * @NM_SETTING_COMPARE_FLAG_EXACT: match all properties exactly + * @NM_SETTING_COMPARE_FLAG_FUZZY: match only important attributes, like SSID, + * type, security settings, etc. Does not match, for example, connection ID + * or UUID. + * @NM_SETTING_COMPARE_FLAG_IGNORE_ID: ignore the connection's ID + * @NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS: ignore secrets + * + * These flags modify the comparison behavior when comparing two settings or + * two connections. + * + **/ +typedef enum { + NM_SETTING_COMPARE_FLAG_EXACT = 0x00000000, + NM_SETTING_COMPARE_FLAG_FUZZY = 0x00000001, + NM_SETTING_COMPARE_FLAG_IGNORE_ID = 0x00000002, + NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS = 0x00000004 +} NMSettingCompareFlags; + +gboolean nm_setting_compare (NMSetting *a, + NMSetting *b, + NMSettingCompareFlags flags); + +void nm_setting_enumerate_values (NMSetting *setting, + NMSettingValueIterFn func, + gpointer user_data); + +char *nm_setting_to_string (NMSetting *setting); + +/* Secrets */ +void nm_setting_clear_secrets (NMSetting *setting); +GPtrArray *nm_setting_need_secrets (NMSetting *setting); +gboolean nm_setting_update_secrets (NMSetting *setting, + GHashTable *secrets, + GError **error); + +G_END_DECLS + +#endif /* NM_SETTING_H */ + diff --git a/libnm-util/nm-utils-private.h b/libnm-util/nm-utils-private.h new file mode 100644 index 00000000..fa1e3a01 --- /dev/null +++ b/libnm-util/nm-utils-private.h @@ -0,0 +1,37 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * Ray Strode <rstrode@redhat.com> + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2005 - 2008 Red Hat, Inc. + */ + +#ifndef __NM_UTILS_PRIVATE_H__ +#define __NM_UTILS_PRIVATE_H__ + +gboolean _nm_utils_string_in_list (const char *str, + const char **valid_strings); + +gboolean _nm_utils_string_slist_validate (GSList *list, + const char **valid_values); + +void _nm_utils_register_value_transformations (void); + +#endif diff --git a/libnm-util/nm-utils.c b/libnm-util/nm-utils.c new file mode 100644 index 00000000..ddb02a22 --- /dev/null +++ b/libnm-util/nm-utils.c @@ -0,0 +1,2104 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* NetworkManager -- Network link manager + * + * Ray Strode <rstrode@redhat.com> + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2005 - 2010 Red Hat, Inc. + */ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <arpa/inet.h> + +#include "wireless-helper.h" + +#include <glib.h> +#include <glib-object.h> +#include <glib/gi18n.h> +#include <dbus/dbus-glib.h> +#include <uuid/uuid.h> + +#include "nm-utils.h" +#include "nm-utils-private.h" +#include "NetworkManager.h" +#include "nm-dbus-glib-types.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "crypto.h" + +/** + * SECTION:nm-utils + * @short_description: Utility functions + * @include: nm-utils.h + * + * A collection of utility functions for working SSIDs, IP addresses, WiFi + * access points and devices, among other things. + */ + +struct EncodingTriplet +{ + const char *encoding1; + const char *encoding2; + const char *encoding3; +}; + +struct IsoLangToEncodings +{ + const char * lang; + struct EncodingTriplet encodings; +}; + +/* 5-letter language codes */ +static const struct IsoLangToEncodings isoLangEntries5[] = +{ + /* Simplified Chinese */ + { "zh_cn", {"euc-cn", "gb2312", "gb18030"} }, /* PRC */ + { "zh_sg", {"euc-cn", "gb2312", "gb18030"} }, /* Singapore */ + + /* Traditional Chinese */ + { "zh_tw", {"big5", "euc-tw", NULL} }, /* Taiwan */ + { "zh_hk", {"big5", "euc-tw", "big5-hkcs"} },/* Hong Kong */ + { "zh_mo", {"big5", "euc-tw", NULL} }, /* Macau */ + + /* Table end */ + { NULL, {NULL, NULL, NULL} } +}; + +/* 2-letter language codes; we don't care about the other 3 in this table */ +static const struct IsoLangToEncodings isoLangEntries2[] = +{ + /* Japanese */ + { "ja", {"euc-jp", "shift_jis", "iso-2022-jp"} }, + + /* Korean */ + { "ko", {"euc-kr", "iso-2022-kr", "johab"} }, + + /* Thai */ + { "th", {"iso-8859-11","windows-874", NULL} }, + + /* Central European */ + { "hu", {"iso-8859-2", "windows-1250", NULL} }, /* Hungarian */ + { "cs", {"iso-8859-2", "windows-1250", NULL} }, /* Czech */ + { "hr", {"iso-8859-2", "windows-1250", NULL} }, /* Croatian */ + { "pl", {"iso-8859-2", "windows-1250", NULL} }, /* Polish */ + { "ro", {"iso-8859-2", "windows-1250", NULL} }, /* Romanian */ + { "sk", {"iso-8859-2", "windows-1250", NULL} }, /* Slovakian */ + { "sl", {"iso-8859-2", "windows-1250", NULL} }, /* Slovenian */ + { "sh", {"iso-8859-2", "windows-1250", NULL} }, /* Serbo-Croatian */ + + /* Cyrillic */ + { "ru", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Russian */ + { "be", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Belorussian */ + { "bg", {"windows-1251","koi8-r", "iso-8859-5"} }, /* Bulgarian */ + { "mk", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Macedonian */ + { "sr", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Serbian */ + { "uk", {"koi8-u", "koi8-r", "windows-1251"} }, /* Ukranian */ + + /* Arabic */ + { "ar", {"iso-8859-6", "windows-1256", NULL} }, + + /* Balitc */ + { "et", {"iso-8859-4", "windows-1257", NULL} }, /* Estonian */ + { "lt", {"iso-8859-4", "windows-1257", NULL} }, /* Lithuanian */ + { "lv", {"iso-8859-4", "windows-1257", NULL} }, /* Latvian */ + + /* Greek */ + { "el", {"iso-8859-7", "windows-1253", NULL} }, + + /* Hebrew */ + { "he", {"iso-8859-8", "windows-1255", NULL} }, + { "iw", {"iso-8859-8", "windows-1255", NULL} }, + + /* Turkish */ + { "tr", {"iso-8859-9", "windows-1254", NULL} }, + + /* Table end */ + { NULL, {NULL, NULL, NULL} } +}; + + +static GHashTable * langToEncodings5 = NULL; +static GHashTable * langToEncodings2 = NULL; + +static void +init_lang_to_encodings_hash (void) +{ + struct IsoLangToEncodings *enc; + + if (G_UNLIKELY (langToEncodings5 == NULL)) { + /* Five-letter codes */ + enc = (struct IsoLangToEncodings *) &isoLangEntries5[0]; + langToEncodings5 = g_hash_table_new (g_str_hash, g_str_equal); + while (enc->lang) { + g_hash_table_insert (langToEncodings5, (gpointer) enc->lang, + (gpointer) &enc->encodings); + enc++; + } + } + + if (G_UNLIKELY (langToEncodings2 == NULL)) { + /* Two-letter codes */ + enc = (struct IsoLangToEncodings *) &isoLangEntries2[0]; + langToEncodings2 = g_hash_table_new (g_str_hash, g_str_equal); + while (enc->lang) { + g_hash_table_insert (langToEncodings2, (gpointer) enc->lang, + (gpointer) &enc->encodings); + enc++; + } + } +} + + +static gboolean +get_encodings_for_lang (const char *lang, + char **encoding1, + char **encoding2, + char **encoding3) +{ + struct EncodingTriplet * encodings; + gboolean success = FALSE; + char * tmp_lang; + + g_return_val_if_fail (lang != NULL, FALSE); + g_return_val_if_fail (encoding1 != NULL, FALSE); + g_return_val_if_fail (encoding2 != NULL, FALSE); + g_return_val_if_fail (encoding3 != NULL, FALSE); + + *encoding1 = "iso-8859-1"; + *encoding2 = "windows-1251"; + *encoding3 = NULL; + + init_lang_to_encodings_hash (); + + tmp_lang = g_strdup (lang); + if ((encodings = g_hash_table_lookup (langToEncodings5, tmp_lang))) + { + *encoding1 = (char *) encodings->encoding1; + *encoding2 = (char *) encodings->encoding2; + *encoding3 = (char *) encodings->encoding3; + success = TRUE; + } + + /* Truncate tmp_lang to length of 2 */ + if (strlen (tmp_lang) > 2) + tmp_lang[2] = '\0'; + if (!success && (encodings = g_hash_table_lookup (langToEncodings2, tmp_lang))) + { + *encoding1 = (char *) encodings->encoding1; + *encoding2 = (char *) encodings->encoding2; + *encoding3 = (char *) encodings->encoding3; + success = TRUE; + } + + g_free (tmp_lang); + return success; +} + +static char * +string_to_utf8 (const char *str, gsize len) +{ + char *converted = NULL; + char *lang, *e1 = NULL, *e2 = NULL, *e3 = NULL; + + g_return_val_if_fail (str != NULL, NULL); + + if (g_utf8_validate (str, len, NULL)) + return g_strdup (str); + + /* LANG may be a good encoding hint */ + g_get_charset ((const char **)(&e1)); + if ((lang = getenv ("LANG"))) { + char * dot; + + lang = g_ascii_strdown (lang, -1); + if ((dot = strchr (lang, '.'))) + *dot = '\0'; + + get_encodings_for_lang (lang, &e1, &e2, &e3); + g_free (lang); + } + + converted = g_convert (str, len, "UTF-8", e1, NULL, NULL, NULL); + if (!converted && e2) + converted = g_convert (str, len, "UTF-8", e2, NULL, NULL, NULL); + + if (!converted && e3) + converted = g_convert (str, len, "UTF-8", e3, NULL, NULL, NULL); + + if (!converted) { + converted = g_convert_with_fallback (str, len, "UTF-8", e1, + "?", NULL, NULL, NULL); + } + + return converted; +} + +/* init, deinit for libnm_util */ + +static gboolean initialized = FALSE; + +/** + * nm_utils_init: + * @error: location to store error, or %NULL + * + * Initializes libnm-util; should be called when starting and program that + * uses libnm-util. Sets up an atexit() handler to ensure de-initialization + * is performed, but calling nm_utils_deinit() to explicitly deinitialize + * libnm-util can also be done. This function can be called more than once. + * + * Returns: TRUE if the initialization was successful, FALSE on failure. + **/ +gboolean +nm_utils_init (GError **error) +{ + if (!initialized) { + if (!crypto_init (error)) + return FALSE; + + _nm_utils_register_value_transformations (); + + atexit (nm_utils_deinit); + initialized = TRUE; + } + return TRUE; +} + +/** + * nm_utils_deinit: + * + * Frees all resources used internally by libnm-util. This function is called + * from an atexit() handler, set up by nm_utils_init(), but is safe to be called + * more than once. Subsequent calls have no effect until nm_utils_init() is + * called again. + **/ +void +nm_utils_deinit (void) +{ + if (initialized) { + crypto_deinit (); + initialized = FALSE; + } +} + +/* ssid helpers */ + +/** + * nm_utils_ssid_to_utf8: + * @ssid: pointer to a buffer containing the SSID data + * @len: length of the SSID data in @ssid + * + * WiFi SSIDs are byte arrays, they are _not_ strings. Thus, an SSID may + * contain embedded NULLs and other unprintable characters. Often it is + * useful to print the SSID out for debugging purposes, but that should be the + * _only_ use of this function. Do not use this function for any persistent + * storage of the SSID, since the printable SSID returned from this function + * cannot be converted back into the real SSID of the access point. + * + * This function does almost everything humanly possible to convert the input + * into a printable UTF-8 string, using roughly the following procedure: + * + * 1) if the input data is already UTF-8 safe, no conversion is performed + * 2) attempts to get the current system language from the LANG environment + * variable, and depending on the language, uses a table of alternative + * encodings to try. For example, if LANG=hu_HU, the table may first try + * the ISO-8859-2 encoding, and if that fails, try the Windows-1250 encoding. + * If all fallback encodings fail, replaces non-UTF-8 characters with '?'. + * 3) If the system language was unable to be determined, falls back to the + * ISO-8859-1 encoding, then to the Windows-1251 encoding. + * 4) If step 3 fails, replaces non-UTF-8 characters with '?'. + * + * Again, this function should be used for debugging and display purposes + * _only_. + * + * Returns: an allocated string containing a UTF-8 representation of the + * SSID, which must be freed by the caller using g_free(). Returns NULL + * on errors. + **/ +char * +nm_utils_ssid_to_utf8 (const char *ssid, guint32 len) +{ + char *converted = NULL, *buf; + gsize buflen = MIN (IW_ESSID_MAX_SIZE, (gsize) len); + + g_return_val_if_fail (ssid != NULL, NULL); + + /* New buffer to ensure NULL-termination of SSID */ + buf = g_malloc0 (IW_ESSID_MAX_SIZE + 1); + memcpy (buf, ssid, buflen); + converted = string_to_utf8 (buf, buflen); + g_free (buf); + return converted; +} + +/* Shamelessly ripped from the Linux kernel ieee80211 stack */ +/** + * nm_utils_is_empty_ssid: + * @ssid: pointer to a buffer containing the SSID data + * @len: length of the SSID data in @ssid + * + * Different manufacturers use different mechanisms for not broadcasting the + * AP's SSID. This function attempts to detect blank/empty SSIDs using a + * number of known SSID-cloaking methods. + * + * Returns: TRUE if the SSID is "empty", FALSE if it is not + **/ +gboolean +nm_utils_is_empty_ssid (const guint8 * ssid, int len) +{ + /* Single white space is for Linksys APs */ + if (len == 1 && ssid[0] == ' ') + return TRUE; + + /* Otherwise, if the entire ssid is 0, we assume it is hidden */ + while (len--) { + if (ssid[len] != '\0') + return FALSE; + } + return TRUE; +} + +/** + * nm_utils_escape_ssid: + * @ssid: pointer to a buffer containing the SSID data + * @len: length of the SSID data in @ssid + * + * This function does a quick printable character conversion of the SSID, simply + * replacing embedded NULLs and non-printable characters with the hexadecimal + * representation of that character. Intended for debugging only, should not + * be used for display of SSIDs. + * + * Returns: pointer to the escaped SSID, which uses an internal static buffer + * and will be overwritten by subsequent calls to this function + **/ +const char * +nm_utils_escape_ssid (const guint8 * ssid, guint32 len) +{ + static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + const guint8 *s = ssid; + char *d = escaped; + + if (nm_utils_is_empty_ssid (ssid, len)) { + memcpy (escaped, "<hidden>", sizeof ("<hidden>")); + return escaped; + } + + len = MIN (len, (guint32) IW_ESSID_MAX_SIZE); + while (len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return escaped; +} + +/** + * nm_utils_same_ssid: + * @ssid1: first SSID data to compare + * @ssid2: second SSID data to compare + * @ignore_trailing_null: TRUE to ignore one trailing NULL byte + * + * Earlier versions of the Linux kernel added a NULL byte to the end of the + * SSID to enable easy printing of the SSID on the console or in a terminal, + * but this behavior was problematic (SSIDs are simply byte arrays, not strings) + * and thus was changed. This function compensates for that behavior at the + * cost of some compatibility with odd SSIDs that may legitimately have trailing + * NULLs, even though that is functionally pointless. + * + * Returns: TRUE if the SSIDs are the same, FALSE if they are not + **/ +gboolean +nm_utils_same_ssid (const GByteArray * ssid1, + const GByteArray * ssid2, + gboolean ignore_trailing_null) +{ + guint32 ssid1_len, ssid2_len; + + if (ssid1 == ssid2) + return TRUE; + if ((ssid1 && !ssid2) || (!ssid1 && ssid2)) + return FALSE; + + ssid1_len = ssid1->len; + ssid2_len = ssid2->len; + if (ssid1_len && ssid2_len && ignore_trailing_null) { + if (ssid1->data[ssid1_len - 1] == '\0') + ssid1_len--; + if (ssid2->data[ssid2_len - 1] == '\0') + ssid2_len--; + } + + if (ssid1_len != ssid2_len) + return FALSE; + + return memcmp (ssid1->data, ssid2->data, ssid1_len) == 0 ? TRUE : FALSE; +} + +static void +value_destroy (gpointer data) +{ + GValue *value = (GValue *) data; + + g_value_unset (value); + g_slice_free (GValue, value); +} + +static void +value_dup (gpointer key, gpointer val, gpointer user_data) +{ + GHashTable *table = (GHashTable *) user_data; + GValue *value = (GValue *) val; + GValue *dup_value; + + dup_value = g_slice_new0 (GValue); + g_value_init (dup_value, G_VALUE_TYPE (val)); + g_value_copy (value, dup_value); + + g_hash_table_insert (table, g_strdup ((char *) key), dup_value); +} + +/** + * nm_utils_gvalue_hash_dup: + * @hash: a #GHashTable mapping string:GValue + * + * Utility function to duplicate a hash table of GValues. + * + * Returns: a newly allocated duplicated #GHashTable, caller must free the + * returned hash with g_hash_table_unref() or g_hash_table_destroy() + **/ +GHashTable * +nm_utils_gvalue_hash_dup (GHashTable *hash) +{ + GHashTable *table; + + g_return_val_if_fail (hash != NULL, NULL); + + table = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + value_destroy); + + g_hash_table_foreach (hash, value_dup, table); + + return table; +} + +/** + * nm_utils_slist_free: + * @list: a #GSList + * @elem_destroy_fn: user function called for each element in @list + * + * Utility function to free a #GSList. + **/ +void +nm_utils_slist_free (GSList *list, GDestroyNotify elem_destroy_fn) +{ + if (!list) + return; + + if (elem_destroy_fn) + g_slist_foreach (list, (GFunc) elem_destroy_fn, NULL); + + g_slist_free (list); +} + +gboolean +_nm_utils_string_in_list (const char *str, const char **valid_strings) +{ + int i; + + for (i = 0; valid_strings[i]; i++) + if (strcmp (str, valid_strings[i]) == 0) + break; + + return valid_strings[i] != NULL; +} + +gboolean +_nm_utils_string_slist_validate (GSList *list, const char **valid_values) +{ + GSList *iter; + + for (iter = list; iter; iter = iter->next) { + if (!_nm_utils_string_in_list ((char *) iter->data, valid_values)) + return FALSE; + } + + return TRUE; +} + +static void +nm_utils_convert_strv_to_slist (const GValue *src_value, GValue *dest_value) +{ + char **str; + GSList *list = NULL; + guint i = 0; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_TYPE_STRV)); + + str = (char **) g_value_get_boxed (src_value); + + while (str && str[i]) + list = g_slist_prepend (list, g_strdup (str[i++])); + + g_value_take_boxed (dest_value, g_slist_reverse (list)); +} + +static void +nm_utils_convert_strv_to_string (const GValue *src_value, GValue *dest_value) +{ + GSList *strings; + GString *printable; + GSList *iter; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_LIST_OF_STRING)); + + strings = (GSList *) g_value_get_boxed (src_value); + + printable = g_string_new ("["); + for (iter = strings; iter; iter = g_slist_next (iter)) { + if (iter != strings) + g_string_append (printable, ", '"); + else + g_string_append_c (printable, '\''); + g_string_append (printable, iter->data); + g_string_append_c (printable, '\''); + } + g_string_append_c (printable, ']'); + + g_value_take_string (dest_value, printable->str); + g_string_free (printable, FALSE); +} + +static void +nm_utils_convert_uint_array_to_string (const GValue *src_value, GValue *dest_value) +{ + GArray *array; + GString *printable; + guint i = 0; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UINT_ARRAY)); + + array = (GArray *) g_value_get_boxed (src_value); + + printable = g_string_new ("["); + while (array && (i < array->len)) { + char buf[INET_ADDRSTRLEN + 1]; + struct in_addr addr; + + if (i > 0) + g_string_append (printable, ", "); + + memset (buf, 0, sizeof (buf)); + addr.s_addr = g_array_index (array, guint32, i++); + if (!inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN)) + nm_warning ("%s: error converting IP4 address 0x%X", + __func__, ntohl (addr.s_addr)); + g_string_append_printf (printable, "%u (%s)", addr.s_addr, buf); + } + g_string_append_c (printable, ']'); + + g_value_take_string (dest_value, printable->str); + g_string_free (printable, FALSE); +} + +static void +nm_utils_convert_ip4_addr_route_struct_array_to_string (const GValue *src_value, GValue *dest_value) +{ + GPtrArray *ptr_array; + GString *printable; + guint i = 0; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT)); + + ptr_array = (GPtrArray *) g_value_get_boxed (src_value); + + printable = g_string_new ("["); + while (ptr_array && (i < ptr_array->len)) { + GArray *array; + char buf[INET_ADDRSTRLEN + 1]; + struct in_addr addr; + gboolean is_addr; /* array contains address x route */ + + if (i > 0) + g_string_append (printable, ", "); + + g_string_append (printable, "{ "); + array = (GArray *) g_ptr_array_index (ptr_array, i++); + if (array->len < 2) { + g_string_append (printable, "invalid"); + continue; + } + is_addr = (array->len < 4); + + memset (buf, 0, sizeof (buf)); + addr.s_addr = g_array_index (array, guint32, 0); + if (!inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN)) + nm_warning ("%s: error converting IP4 address 0x%X", + __func__, ntohl (addr.s_addr)); + if (is_addr) + g_string_append_printf (printable, "ip = %s", buf); + else + g_string_append_printf (printable, "dst = %s", buf); + g_string_append (printable, ", "); + + memset (buf, 0, sizeof (buf)); + g_string_append_printf (printable, "px = %u", + g_array_index (array, guint32, 1)); + + if (array->len > 2) { + g_string_append (printable, ", "); + + memset (buf, 0, sizeof (buf)); + addr.s_addr = g_array_index (array, guint32, 2); + if (!inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN)) + nm_warning ("%s: error converting IP4 address 0x%X", + __func__, ntohl (addr.s_addr)); + if (is_addr) + g_string_append_printf (printable, "gw = %s", buf); + else + g_string_append_printf (printable, "nh = %s", buf); + } + + if (array->len > 3) { + g_string_append (printable, ", "); + + memset (buf, 0, sizeof (buf)); + g_string_append_printf (printable, "mt = %u", + g_array_index (array, guint32, 3)); + } + + g_string_append (printable, " }"); + } + g_string_append_c (printable, ']'); + + g_value_take_string (dest_value, printable->str); + g_string_free (printable, FALSE); +} + +static void +convert_one_gvalue_hash_entry (gpointer key, gpointer value, gpointer user_data) +{ + GString *printable = (GString *) user_data; + char *value_as_string; + + value_as_string = g_strdup_value_contents ((GValue *) value); + g_string_append_printf (printable, " { '%s': %s },", (const char *) key, value_as_string); + g_free (value_as_string); +} + +static void +nm_utils_convert_gvalue_hash_to_string (const GValue *src_value, GValue *dest_value) +{ + GHashTable *hash; + GString *printable; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_MAP_OF_VARIANT)); + + hash = (GHashTable *) g_value_get_boxed (src_value); + + printable = g_string_new ("["); + g_hash_table_foreach (hash, convert_one_gvalue_hash_entry, printable); + g_string_append (printable, " ]"); + + g_value_take_string (dest_value, printable->str); + g_string_free (printable, FALSE); +} + +static void +convert_one_string_hash_entry (gpointer key, gpointer value, gpointer user_data) +{ + GString *printable = (GString *) user_data; + + g_string_append_printf (printable, " { '%s': %s },", (const char *) key, (const char *) value); +} + +static void +nm_utils_convert_string_hash_to_string (const GValue *src_value, GValue *dest_value) +{ + GHashTable *hash; + GString *printable; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_MAP_OF_STRING)); + + hash = (GHashTable *) g_value_get_boxed (src_value); + + printable = g_string_new ("["); + if (hash) + g_hash_table_foreach (hash, convert_one_string_hash_entry, printable); + g_string_append (printable, " ]"); + + g_value_take_string (dest_value, printable->str); + g_string_free (printable, FALSE); +} + +static void +nm_utils_convert_byte_array_to_string (const GValue *src_value, GValue *dest_value) +{ + GArray *array; + GString *printable; + guint i = 0; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UCHAR_ARRAY)); + + array = (GArray *) g_value_get_boxed (src_value); + + printable = g_string_new ("["); + if (array) { + while (i < MIN (array->len, 35)) { + if (i > 0) + g_string_append_c (printable, ' '); + g_string_append_printf (printable, "0x%02X", + g_array_index (array, unsigned char, i++)); + } + if (i < array->len) + g_string_append (printable, " ... "); + } + g_string_append_c (printable, ']'); + + g_value_take_string (dest_value, printable->str); + g_string_free (printable, FALSE); +} + +static gboolean +nm_utils_inet6_ntop (struct in6_addr *addr, char *buf) +{ + if (!inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN)) { + int i; + GString *ip6_str = g_string_new (NULL); + g_string_append_printf (ip6_str, "%02X", addr->s6_addr[0]); + for (i = 1; i < 16; i++) + g_string_append_printf (ip6_str, " %02X", addr->s6_addr[i]); + nm_warning ("%s: error converting IP6 address %s", + __func__, ip6_str->str); + g_string_free (ip6_str, TRUE); + return FALSE; + } + return TRUE; +} + +static void +nm_utils_convert_ip6_dns_array_to_string (const GValue *src_value, GValue *dest_value) +{ + GPtrArray *ptr_array; + GString *printable; + guint i = 0; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR)); + + ptr_array = (GPtrArray *) g_value_get_boxed (src_value); + + printable = g_string_new ("["); + while (ptr_array && (i < ptr_array->len)) { + GByteArray *bytearray; + char buf[INET6_ADDRSTRLEN]; + struct in6_addr *addr; + + if (i > 0) + g_string_append (printable, ", "); + + bytearray = (GByteArray *) g_ptr_array_index (ptr_array, i++); + if (bytearray->len != 16) { + g_string_append (printable, "invalid"); + continue; + } + addr = (struct in6_addr *) bytearray->data; + memset (buf, 0, sizeof (buf)); + nm_utils_inet6_ntop (addr, buf); + g_string_append_printf (printable, "%s", buf); + } + g_string_append_c (printable, ']'); + + g_value_take_string (dest_value, printable->str); + g_string_free (printable, FALSE); +} + +static void +nm_utils_convert_ip6_addr_struct_array_to_string (const GValue *src_value, GValue *dest_value) +{ + GPtrArray *ptr_array; + GString *printable; + guint i = 0; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS)); + + ptr_array = (GPtrArray *) g_value_get_boxed (src_value); + + printable = g_string_new ("["); + while (ptr_array && (i < ptr_array->len)) { + GValueArray *elements; + GValue *tmp; + GByteArray *ba_addr; + char buf[INET6_ADDRSTRLEN]; + struct in6_addr *addr; + guint32 prefix; + + if (i > 0) + g_string_append (printable, ", "); + + g_string_append (printable, "{ "); + elements = (GValueArray *) g_ptr_array_index (ptr_array, i++); + if ( (elements->n_values != 3) + || (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY) + || (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT) + || (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)) { + g_string_append (printable, "invalid }"); + continue; + } + + /* IPv6 address */ + tmp = g_value_array_get_nth (elements, 0); + ba_addr = g_value_get_boxed (tmp); + if (ba_addr->len != 16) { + g_string_append (printable, "invalid }"); + continue; + } + addr = (struct in6_addr *) ba_addr->data; + memset (buf, 0, sizeof (buf)); + nm_utils_inet6_ntop (addr, buf); + g_string_append_printf (printable, "ip = %s", buf); + g_string_append (printable, ", "); + + /* Prefix */ + tmp = g_value_array_get_nth (elements, 1); + prefix = g_value_get_uint (tmp); + if (prefix > 128) { + g_string_append (printable, "invalid }"); + continue; + } + g_string_append_printf (printable, "px = %u", prefix); + g_string_append (printable, ", "); + + /* IPv6 Gateway */ + tmp = g_value_array_get_nth (elements, 2); + ba_addr = g_value_get_boxed (tmp); + if (ba_addr->len != 16) { + g_string_append (printable, "invalid }"); + continue; + } + addr = (struct in6_addr *) ba_addr->data; + memset (buf, 0, sizeof (buf)); + nm_utils_inet6_ntop (addr, buf); + g_string_append_printf (printable, "gw = %s", buf); + g_string_append (printable, " }"); + } + g_string_append_c (printable, ']'); + + g_value_take_string (dest_value, printable->str); + g_string_free (printable, FALSE); +} + +static void +nm_utils_convert_ip6_route_struct_array_to_string (const GValue *src_value, GValue *dest_value) +{ + GPtrArray *ptr_array; + GString *printable; + guint i = 0; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE)); + + ptr_array = (GPtrArray *) g_value_get_boxed (src_value); + + printable = g_string_new ("["); + while (ptr_array && (i < ptr_array->len)) { + GValueArray *elements; + GValue *tmp; + GByteArray *ba_addr; + char buf[INET6_ADDRSTRLEN]; + struct in6_addr *addr; + guint32 prefix, metric; + + if (i > 0) + g_string_append (printable, ", "); + + g_string_append (printable, "{ "); + elements = (GValueArray *) g_ptr_array_index (ptr_array, i++); + if ( (elements->n_values != 4) + || (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY) + || (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT) + || (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY) + || (G_VALUE_TYPE (g_value_array_get_nth (elements, 3)) != G_TYPE_UINT)) { + g_string_append (printable, "invalid"); + continue; + } + + /* Destination address */ + tmp = g_value_array_get_nth (elements, 0); + ba_addr = g_value_get_boxed (tmp); + if (ba_addr->len != 16) { + g_string_append (printable, "invalid"); + continue; + } + addr = (struct in6_addr *) ba_addr->data; + memset (buf, 0, sizeof (buf)); + nm_utils_inet6_ntop (addr, buf); + g_string_append_printf (printable, "dst = %s", buf); + g_string_append (printable, ", "); + + /* Prefix */ + tmp = g_value_array_get_nth (elements, 1); + prefix = g_value_get_uint (tmp); + if (prefix > 128) { + g_string_append (printable, "invalid"); + continue; + } + g_string_append_printf (printable, "px = %u", prefix); + g_string_append (printable, ", "); + + /* Next hop addresses */ + tmp = g_value_array_get_nth (elements, 2); + ba_addr = g_value_get_boxed (tmp); + if (ba_addr->len != 16) { + g_string_append (printable, "invalid"); + continue; + } + addr = (struct in6_addr *) ba_addr->data; + memset (buf, 0, sizeof (buf)); + nm_utils_inet6_ntop (addr, buf); + g_string_append_printf (printable, "nh = %s", buf); + g_string_append (printable, ", "); + + /* Metric */ + tmp = g_value_array_get_nth (elements, 3); + metric = g_value_get_uint (tmp); + g_string_append_printf (printable, "mt = %u", metric); + + g_string_append (printable, " }"); + } + g_string_append_c (printable, ']'); + + g_value_take_string (dest_value, printable->str); + g_string_free (printable, FALSE); +} + +#define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID)) +#define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS)) + +static void +nm_utils_convert_old_ip6_addr_array (const GValue *src_value, GValue *dst_value) +{ + GPtrArray *src_outer_array; + GPtrArray *dst_outer_array; + guint i; + + g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS)); + + src_outer_array = (GPtrArray *) g_value_get_boxed (src_value); + dst_outer_array = g_ptr_array_new (); + + for (i = 0; src_outer_array && (i < src_outer_array->len); i++) { + GValueArray *src_addr_array; + GValueArray *dst_addr_array; + GValue element = {0, }; + GValue *src_addr, *src_prefix; + GByteArray *ba; + + src_addr_array = (GValueArray *) g_ptr_array_index (src_outer_array, i); + + if ( (src_addr_array->n_values != 2) + || (G_VALUE_TYPE (g_value_array_get_nth (src_addr_array, 0)) != DBUS_TYPE_G_UCHAR_ARRAY) + || (G_VALUE_TYPE (g_value_array_get_nth (src_addr_array, 1)) != G_TYPE_UINT)) { + g_warning ("%s: invalid old IPv6 address type", __func__); + return; + } + + dst_addr_array = g_value_array_new (3); + + src_addr = g_value_array_get_nth (src_addr_array, 0); + g_value_array_append (dst_addr_array, src_addr); + src_prefix = g_value_array_get_nth (src_addr_array, 1); + g_value_array_append (dst_addr_array, src_prefix); + + /* Blank Gateway */ + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + ba = g_byte_array_new (); + g_byte_array_append (ba, (guint8 *) "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16); + g_value_take_boxed (&element, ba); + g_value_array_append (dst_addr_array, &element); + g_value_unset (&element); + + g_ptr_array_add (dst_outer_array, dst_addr_array); + } + + g_value_take_boxed (dst_value, dst_outer_array); +} + +void +_nm_utils_register_value_transformations (void) +{ + static gboolean registered = FALSE; + + if (G_UNLIKELY (!registered)) { + g_value_register_transform_func (G_TYPE_STRV, + DBUS_TYPE_G_LIST_OF_STRING, + nm_utils_convert_strv_to_slist); + g_value_register_transform_func (DBUS_TYPE_G_LIST_OF_STRING, + G_TYPE_STRING, + nm_utils_convert_strv_to_string); + g_value_register_transform_func (DBUS_TYPE_G_UINT_ARRAY, + G_TYPE_STRING, + nm_utils_convert_uint_array_to_string); + g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, + G_TYPE_STRING, + nm_utils_convert_ip4_addr_route_struct_array_to_string); + g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_STRING, + nm_utils_convert_gvalue_hash_to_string); + g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_STRING, + G_TYPE_STRING, + nm_utils_convert_string_hash_to_string); + g_value_register_transform_func (DBUS_TYPE_G_UCHAR_ARRAY, + G_TYPE_STRING, + nm_utils_convert_byte_array_to_string); + g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR, + G_TYPE_STRING, + nm_utils_convert_ip6_dns_array_to_string); + g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS, + G_TYPE_STRING, + nm_utils_convert_ip6_addr_struct_array_to_string); + g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE, + G_TYPE_STRING, + nm_utils_convert_ip6_route_struct_array_to_string); + g_value_register_transform_func (OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS, + DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS, + nm_utils_convert_old_ip6_addr_array); + registered = TRUE; + } +} + +static gboolean +device_supports_ap_ciphers (guint32 dev_caps, + guint32 ap_flags, + gboolean static_wep) +{ + gboolean have_pair = FALSE; + gboolean have_group = FALSE; + /* Device needs to support at least one pairwise and one group cipher */ + + /* Pairwise */ + if (static_wep) { + /* Static WEP only uses group ciphers */ + have_pair = TRUE; + } else { + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP40) + if (ap_flags & NM_802_11_AP_SEC_PAIR_WEP40) + have_pair = TRUE; + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP104) + if (ap_flags & NM_802_11_AP_SEC_PAIR_WEP104) + have_pair = TRUE; + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP) + if (ap_flags & NM_802_11_AP_SEC_PAIR_TKIP) + have_pair = TRUE; + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP) + if (ap_flags & NM_802_11_AP_SEC_PAIR_CCMP) + have_pair = TRUE; + } + + /* Group */ + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP40) + if (ap_flags & NM_802_11_AP_SEC_GROUP_WEP40) + have_group = TRUE; + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP104) + if (ap_flags & NM_802_11_AP_SEC_GROUP_WEP104) + have_group = TRUE; + if (!static_wep) { + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP) + if (ap_flags & NM_802_11_AP_SEC_GROUP_TKIP) + have_group = TRUE; + if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP) + if (ap_flags & NM_802_11_AP_SEC_GROUP_CCMP) + have_group = TRUE; + } + + return (have_pair && have_group); +} + +/** + * nm_utils_security_valid: + * @type: the security type to check AP flags and device capabilties against, + * e.g. #NMU_SEC_STATIC_WEP + * @wifi_caps: bitfield of the capabilities of the specific WiFi device, e.g. + * #NM_WIFI_DEVICE_CAP_CIPHER_WEP40 + * @have_ap: whether the @ap_flags, @ap_wpa, and @ap_rsn arguments are valid + * @adhoc: whether the capabilities being tested are from an Ad-Hoc AP (IBSS) + * @ap_flags: bitfield of AP capabilities, e.g. #NM_802_11_AP_FLAGS_PRIVACY + * @ap_wpa: bitfield of AP capabilties derived from the AP's WPA beacon, + * e.g. (#NM_802_11_AP_SEC_PAIR_TKIP | #NM_802_11_AP_SEC_KEY_MGMT_PSK) + * @ap_rsn: bitfield of AP capabilties derived from the AP's RSN/WPA2 beacon, + * e.g. (#NM_802_11_AP_SEC_PAIR_CCMP | #NM_802_11_AP_SEC_PAIR_TKIP) + * + * Given a set of device capabilities, and a desired security type to check + * against, determines whether the combination of device, desired security + * type, and AP capabilities intersect. + * + * Returns: TRUE if the device capabilities and AP capabilties intersect and are + * compatible with the desired @type, FALSE if they are not + **/ +gboolean +nm_utils_security_valid (NMUtilsSecurityType type, + guint32 wifi_caps, + gboolean have_ap, + gboolean adhoc, + guint32 ap_flags, + guint32 ap_wpa, + guint32 ap_rsn) +{ + gboolean good = TRUE; + + if (!have_ap) { + if (type == NMU_SEC_NONE) + return TRUE; + if ( (type == NMU_SEC_STATIC_WEP) + || ((type == NMU_SEC_DYNAMIC_WEP) && !adhoc) + || ((type == NMU_SEC_LEAP) && !adhoc)) { + if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104)) + return TRUE; + } + } + + switch (type) { + case NMU_SEC_NONE: + g_assert (have_ap); + if (ap_flags & NM_802_11_AP_FLAGS_PRIVACY) + return FALSE; + if (ap_wpa || ap_rsn) + return FALSE; + break; + case NMU_SEC_LEAP: /* require PRIVACY bit for LEAP? */ + if (adhoc) + return FALSE; + /* Fall through */ + case NMU_SEC_STATIC_WEP: + g_assert (have_ap); + if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) + return FALSE; + if (ap_wpa || ap_rsn) { + if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, TRUE)) + if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, TRUE)) + return FALSE; + } + break; + case NMU_SEC_DYNAMIC_WEP: + if (adhoc) + return FALSE; + g_assert (have_ap); + if (ap_rsn || !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) + return FALSE; + /* Some APs broadcast minimal WPA-enabled beacons that must be handled */ + if (ap_wpa) { + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE)) + return FALSE; + } + break; + case NMU_SEC_WPA_PSK: + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA)) + return FALSE; + if (have_ap) { + /* Ad-Hoc WPA APs won't necessarily have the PSK flag set */ + if ((ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) || adhoc) { + if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) + return TRUE; + if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; + } + return FALSE; + } + break; + case NMU_SEC_WPA2_PSK: + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) + return FALSE; + if (have_ap) { + /* Ad-Hoc WPA APs won't necessarily have the PSK flag set */ + if ((ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) || adhoc) { + if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)) + return TRUE; + if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP) + && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)) + return TRUE; + } + return FALSE; + } + break; + case NMU_SEC_WPA_ENTERPRISE: + if (adhoc) + return FALSE; + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA)) + return FALSE; + if (have_ap) { + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + /* Ensure at least one WPA cipher is supported */ + if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE)) + return FALSE; + } + break; + case NMU_SEC_WPA2_ENTERPRISE: + if (adhoc) + return FALSE; + if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN)) + return FALSE; + if (have_ap) { + if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + /* Ensure at least one WPA cipher is supported */ + if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, FALSE)) + return FALSE; + } + break; + default: + good = FALSE; + break; + } + + return good; +} + +/** + * nm_utils_ip4_addresses_from_gvalue: + * @value: gvalue containing a GPtrArray of GArrays of guint32s + * + * Utility function to convert a #GPtrArray of #GArrays of guint32s representing + * a list of NetworkManager IPv4 addresses (which is a tuple of address, gateway, + * and prefix) into a GSList of #NMIP4Address objects. The specific format of + * this serialization is not guaranteed to be stable and the #GArray may be + * extended in the future. + * + * Returns: a newly allocated #GSList of #NMIP4Address objects + **/ +GSList * +nm_utils_ip4_addresses_from_gvalue (const GValue *value) +{ + GPtrArray *addresses; + int i; + GSList *list = NULL; + + addresses = (GPtrArray *) g_value_get_boxed (value); + for (i = 0; addresses && (i < addresses->len); i++) { + GArray *array = (GArray *) g_ptr_array_index (addresses, i); + NMIP4Address *addr; + + if (array->len < 3) { + nm_warning ("Ignoring invalid IP4 address"); + continue; + } + + addr = nm_ip4_address_new (); + nm_ip4_address_set_address (addr, g_array_index (array, guint32, 0)); + nm_ip4_address_set_prefix (addr, g_array_index (array, guint32, 1)); + nm_ip4_address_set_gateway (addr, g_array_index (array, guint32, 2)); + list = g_slist_prepend (list, addr); + } + + return g_slist_reverse (list); +} + +/** + * nm_utils_ip4_addresses_to_gvalue: + * @list: a list of #NMIP4Address objects + * @value: a pointer to a #GValue into which to place the converted addresses, + * which should be unset by the caller (when no longer needed) with + * g_value_unset(). + * + * Utility function to convert a #GSList of #NMIP4Address objects into a + * GPtrArray of GArrays of guint32s representing a list of NetworkManager IPv4 + * addresses (which is a tuple of address, gateway, and prefix). The specific + * format of this serialization is not guaranteed to be stable and may be + * extended in the future. + **/ +void +nm_utils_ip4_addresses_to_gvalue (GSList *list, GValue *value) +{ + GPtrArray *addresses; + GSList *iter; + + addresses = g_ptr_array_new (); + + for (iter = list; iter; iter = iter->next) { + NMIP4Address *addr = (NMIP4Address *) iter->data; + GArray *array; + guint32 tmp; + + array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3); + + tmp = nm_ip4_address_get_address (addr); + g_array_append_val (array, tmp); + + tmp = nm_ip4_address_get_prefix (addr); + g_array_append_val (array, tmp); + + tmp = nm_ip4_address_get_gateway (addr); + g_array_append_val (array, tmp); + + g_ptr_array_add (addresses, array); + } + + g_value_take_boxed (value, addresses); +} + +/** + * nm_utils_ip4_routes_from_gvalue: + * @value: gvalue containing a GPtrArray of GArrays of guint32s + * + * Utility function to convert a GPtrArray of GArrays of guint32s representing + * a list of NetworkManager IPv4 routes (which is a tuple of route, next hop, + * prefix, and metric) into a GSList of #NMIP4Route objects. The specific + * format of this serialization is not guaranteed to be stable and may be + * extended in the future. + * + * Returns: a newly allocated #GSList of #NMIP4Route objects + **/ +GSList * +nm_utils_ip4_routes_from_gvalue (const GValue *value) +{ + GPtrArray *routes; + int i; + GSList *list = NULL; + + routes = (GPtrArray *) g_value_get_boxed (value); + for (i = 0; routes && (i < routes->len); i++) { + GArray *array = (GArray *) g_ptr_array_index (routes, i); + NMIP4Route *route; + + if (array->len < 4) { + nm_warning ("Ignoring invalid IP4 route"); + continue; + } + + route = nm_ip4_route_new (); + nm_ip4_route_set_dest (route, g_array_index (array, guint32, 0)); + nm_ip4_route_set_prefix (route, g_array_index (array, guint32, 1)); + nm_ip4_route_set_next_hop (route, g_array_index (array, guint32, 2)); + nm_ip4_route_set_metric (route, g_array_index (array, guint32, 3)); + list = g_slist_prepend (list, route); + } + + return g_slist_reverse (list); +} + +/** + * nm_utils_ip4_routes_to_gvalue: + * @list: a list of #NMIP4Route objects + * @value: a pointer to a #GValue into which to place the converted routes, + * which should be unset by the caller (when no longer needed) with + * g_value_unset(). + * + * Utility function to convert a #GSList of #NMIP4Route objects into a + * GPtrArray of GArrays of guint32s representing a list of NetworkManager IPv4 + * routes (which is a tuple of route, next hop, prefix, and metric). The + * specific format of this serialization is not guaranteed to be stable and may + * be extended in the future. + **/ +void +nm_utils_ip4_routes_to_gvalue (GSList *list, GValue *value) +{ + GPtrArray *routes; + GSList *iter; + + routes = g_ptr_array_new (); + + for (iter = list; iter; iter = iter->next) { + NMIP4Route *route = (NMIP4Route *) iter->data; + GArray *array; + guint32 tmp; + + array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3); + + tmp = nm_ip4_route_get_dest (route); + g_array_append_val (array, tmp); + + tmp = nm_ip4_route_get_prefix (route); + g_array_append_val (array, tmp); + + tmp = nm_ip4_route_get_next_hop (route); + g_array_append_val (array, tmp); + + tmp = nm_ip4_route_get_metric (route); + g_array_append_val (array, tmp); + + g_ptr_array_add (routes, array); + } + + g_value_take_boxed (value, routes); +} + +/** + * nm_utils_ip4_netmask_to_prefix: + * @netmask: an IPv4 netmask in network byte order + * + * Returns: the CIDR prefix represented by the netmask + **/ +guint32 +nm_utils_ip4_netmask_to_prefix (guint32 netmask) +{ + guchar *p, *end; + guint32 prefix = 0; + + p = (guchar *) &netmask; + end = p + sizeof (guint32); + + while ((*p == 0xFF) && p < end) { + prefix += 8; + p++; + } + + if (p < end) { + guchar v = *p; + + while (v) { + prefix++; + v <<= 1; + } + } + + return prefix; +} + +/** + * nm_utils_ip4_prefix_to_netmask: + * @prefix: a CIDR prefix + * + * Returns: the netmask represented by the prefix + **/ +guint32 +nm_utils_ip4_prefix_to_netmask (guint32 prefix) +{ + guint32 msk = 0x80000000; + guint32 netmask = 0; + + while (prefix > 0) { + netmask |= msk; + msk >>= 1; + prefix--; + } + + return (guint32) htonl (netmask); +} + + +/** + * nm_utils_ip4_get_default_prefix: + * @ip: an IPv4 address (in network byte order) + * + * When the Internet was originally set up, various ranges of IP addresses were + * segmented into three network classes: A, B, and C. This function will return + * a prefix that is associated with the IP address specified defining where it + * falls in the predefined classes. + * + * Returns: the default class prefix for the given IP + **/ +/* The function is originally from ipcalc.c of Red Hat's initscripts. */ +guint32 +nm_utils_ip4_get_default_prefix (guint32 ip) +{ + if (((ntohl (ip) & 0xFF000000) >> 24) <= 127) + return 8; /* Class A - 255.0.0.0 */ + else if (((ntohl (ip) & 0xFF000000) >> 24) <= 191) + return 16; /* Class B - 255.255.0.0 */ + + return 24; /* Class C - 255.255.255.0 */ +} + +/** + * nm_utils_ip6_addresses_from_gvalue: + * @value: gvalue containing a GPtrArray of GValueArrays of (GArray of guchars) and guint32 + * + * Utility function to convert a #GPtrArray of #GValueArrays of (#GArray of guchars) and guint32 + * representing a list of NetworkManager IPv6 addresses (which is a tuple of address, + * prefix, and gateway), into a GSList of #NMIP6Address objects. The specific format of + * this serialization is not guaranteed to be stable and the #GValueArray may be + * extended in the future. + * + * Returns: a newly allocated #GSList of #NMIP6Address objects + **/ +GSList * +nm_utils_ip6_addresses_from_gvalue (const GValue *value) +{ + GPtrArray *addresses; + int i; + GSList *list = NULL; + + addresses = (GPtrArray *) g_value_get_boxed (value); + + for (i = 0; addresses && (i < addresses->len); i++) { + GValueArray *elements = (GValueArray *) g_ptr_array_index (addresses, i); + GValue *tmp; + GByteArray *ba_addr; + GByteArray *ba_gw = NULL; + NMIP6Address *addr; + guint32 prefix; + + if (elements->n_values < 2 || elements->n_values > 3) { + nm_warning ("%s: ignoring invalid IP6 address structure", __func__); + continue; + } + + if ( (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY) + || (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)) { + nm_warning ("%s: ignoring invalid IP6 address structure", __func__); + continue; + } + + /* Check optional 3rd element (gateway) */ + if ( elements->n_values == 3 + && (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)) { + nm_warning ("%s: ignoring invalid IP6 address structure", __func__); + continue; + } + + tmp = g_value_array_get_nth (elements, 0); + ba_addr = g_value_get_boxed (tmp); + if (ba_addr->len != 16) { + nm_warning ("%s: ignoring invalid IP6 address of length %d", + __func__, ba_addr->len); + continue; + } + + tmp = g_value_array_get_nth (elements, 1); + prefix = g_value_get_uint (tmp); + if (prefix > 128) { + nm_warning ("%s: ignoring invalid IP6 prefix %d", + __func__, prefix); + continue; + } + + if (elements->n_values == 3) { + tmp = g_value_array_get_nth (elements, 2); + ba_gw = g_value_get_boxed (tmp); + if (ba_gw->len != 16) { + nm_warning ("%s: ignoring invalid IP6 gateway address of length %d", + __func__, ba_gw->len); + continue; + } + } + + addr = nm_ip6_address_new (); + nm_ip6_address_set_prefix (addr, prefix); + nm_ip6_address_set_address (addr, (const struct in6_addr *) ba_addr->data); + if (ba_gw) + nm_ip6_address_set_gateway (addr, (const struct in6_addr *) ba_gw->data); + + list = g_slist_prepend (list, addr); + } + + return g_slist_reverse (list); +} + +/** + * nm_utils_ip6_addresses_to_gvalue: + * @list: a list of #NMIP6Address objects + * @value: a pointer to a #GValue into which to place the converted addresses, + * which should be unset by the caller (when no longer needed) with + * g_value_unset(). + * + * Utility function to convert a #GSList of #NMIP6Address objects into a + * GPtrArray of GValueArrays representing a list of NetworkManager IPv6 addresses + * (which is a tuple of address, prefix, and gateway). The specific format of + * this serialization is not guaranteed to be stable and may be extended in the + * future. + **/ +void +nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value) +{ + GPtrArray *addresses; + GSList *iter; + + addresses = g_ptr_array_new (); + + for (iter = list; iter; iter = iter->next) { + NMIP6Address *addr = (NMIP6Address *) iter->data; + GValueArray *array; + GValue element = {0, }; + GByteArray *ba; + + array = g_value_array_new (3); + + /* IP address */ + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + ba = g_byte_array_new (); + g_byte_array_append (ba, (guint8 *) nm_ip6_address_get_address (addr), 16); + g_value_take_boxed (&element, ba); + g_value_array_append (array, &element); + g_value_unset (&element); + + /* Prefix */ + g_value_init (&element, G_TYPE_UINT); + g_value_set_uint (&element, nm_ip6_address_get_prefix (addr)); + g_value_array_append (array, &element); + g_value_unset (&element); + + /* Gateway */ + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + ba = g_byte_array_new (); + g_byte_array_append (ba, (guint8 *) nm_ip6_address_get_gateway (addr), 16); + g_value_take_boxed (&element, ba); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_ptr_array_add (addresses, array); + } + + g_value_take_boxed (value, addresses); +} + +/** + * nm_utils_ip6_routes_from_gvalue: + * @value: gvalue containing a GPtrArray of GValueArrays of (GArray or guchars), guint32, + * (GArray of guchars), and guint32 + * + * Utility function GPtrArray of GValueArrays of (GArray or guchars), guint32, + * (GArray of guchars), and guint32 representing a list of NetworkManager IPv6 + * routes (which is a tuple of destination, prefix, next hop, and metric) + * into a GSList of #NMIP6Route objects. The specific format of this serialization + * is not guaranteed to be stable and may be extended in the future. + * + * Returns: a newly allocated #GSList of #NMIP6Route objects + **/ +GSList * +nm_utils_ip6_routes_from_gvalue (const GValue *value) +{ + GPtrArray *routes; + int i; + GSList *list = NULL; + + routes = (GPtrArray *) g_value_get_boxed (value); + for (i = 0; routes && (i < routes->len); i++) { + GValueArray *route_values = (GValueArray *) g_ptr_array_index (routes, i); + GByteArray *dest, *next_hop; + guint prefix, metric; + NMIP6Route *route; + + if ( (route_values->n_values != 4) + || (G_VALUE_TYPE (g_value_array_get_nth (route_values, 0)) != DBUS_TYPE_G_UCHAR_ARRAY) + || (G_VALUE_TYPE (g_value_array_get_nth (route_values, 1)) != G_TYPE_UINT) + || (G_VALUE_TYPE (g_value_array_get_nth (route_values, 2)) != DBUS_TYPE_G_UCHAR_ARRAY) + || (G_VALUE_TYPE (g_value_array_get_nth (route_values, 3)) != G_TYPE_UINT)) { + nm_warning ("Ignoring invalid IP6 route"); + continue; + } + + dest = g_value_get_boxed (g_value_array_get_nth (route_values, 0)); + if (dest->len != 16) { + nm_warning ("%s: ignoring invalid IP6 dest address of length %d", + __func__, dest->len); + continue; + } + + prefix = g_value_get_uint (g_value_array_get_nth (route_values, 1)); + + next_hop = g_value_get_boxed (g_value_array_get_nth (route_values, 2)); + if (next_hop->len != 16) { + nm_warning ("%s: ignoring invalid IP6 next_hop address of length %d", + __func__, next_hop->len); + continue; + } + + metric = g_value_get_uint (g_value_array_get_nth (route_values, 3)); + + route = nm_ip6_route_new (); + nm_ip6_route_set_dest (route, (struct in6_addr *)dest->data); + nm_ip6_route_set_prefix (route, prefix); + nm_ip6_route_set_next_hop (route, (struct in6_addr *)next_hop->data); + nm_ip6_route_set_metric (route, metric); + list = g_slist_prepend (list, route); + } + + return g_slist_reverse (list); +} + +/** + * nm_utils_ip6_routes_to_gvalue: + * @list: a list of #NMIP6Route objects + * @value: a pointer to a #GValue into which to place the converted routes, + * which should be unset by the caller (when no longer needed) with + * g_value_unset(). + * + * Utility function to convert a #GSList of #NMIP6Route objects into a GPtrArray of + * GValueArrays of (GArray or guchars), guint32, (GArray of guchars), and guint32 + * representing a list of NetworkManager IPv6 routes (which is a tuple of destination, + * prefix, next hop, and metric). The specific format of this serialization is not + * guaranteed to be stable and may be extended in the future. + **/ +void +nm_utils_ip6_routes_to_gvalue (GSList *list, GValue *value) +{ + GPtrArray *routes; + GSList *iter; + + routes = g_ptr_array_new (); + + for (iter = list; iter; iter = iter->next) { + NMIP6Route *route = (NMIP6Route *) iter->data; + GValueArray *array; + const struct in6_addr *addr; + GByteArray *ba; + GValue element = {0, }; + + array = g_value_array_new (4); + + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + addr = nm_ip6_route_get_dest (route); + ba = g_byte_array_new (); + g_byte_array_append (ba, (guchar *)addr, sizeof (*addr)); + g_value_take_boxed (&element, ba); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_value_init (&element, G_TYPE_UINT); + g_value_set_uint (&element, nm_ip6_route_get_prefix (route)); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + addr = nm_ip6_route_get_next_hop (route); + ba = g_byte_array_new (); + g_byte_array_append (ba, (guchar *)addr, sizeof (*addr)); + g_value_take_boxed (&element, ba); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_value_init (&element, G_TYPE_UINT); + g_value_set_uint (&element, nm_ip6_route_get_metric (route)); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_ptr_array_add (routes, array); + } + + g_value_take_boxed (value, routes); +} + +GSList * +nm_utils_ip6_dns_from_gvalue (const GValue *value) +{ + GPtrArray *dns; + int i; + GSList *list = NULL; + + dns = (GPtrArray *) g_value_get_boxed (value); + for (i = 0; dns && (i < dns->len); i++) { + GByteArray *bytearray = (GByteArray *) g_ptr_array_index (dns, i); + struct in6_addr *addr; + + if (bytearray->len != 16) { + nm_warning ("%s: ignoring invalid IP6 address of length %d", + __func__, bytearray->len); + continue; + } + + addr = g_malloc0 (sizeof (struct in6_addr)); + memcpy (addr->s6_addr, bytearray->data, bytearray->len); + list = g_slist_prepend (list, addr); + } + + return g_slist_reverse (list); +} + +void +nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value) +{ + GPtrArray *dns; + GSList *iter; + + dns = g_ptr_array_new (); + + for (iter = list; iter; iter = iter->next) { + struct in6_addr *addr = (struct in6_addr *) iter->data; + GByteArray *bytearray; + + bytearray = g_byte_array_sized_new (16); + g_byte_array_append (bytearray, (guint8 *) addr->s6_addr, 16); + g_ptr_array_add (dns, bytearray); + } + + g_value_take_boxed (value, dns); +} + +/** + * nm_utils_uuid_generate: + * + * Returns: a newly allocated UUID suitable for use as the #NMSettingConnection + * object's #NMSettingConnection:id: property. Should be freed with g_free() + **/ +char * +nm_utils_uuid_generate (void) +{ + uuid_t uuid; + char *buf; + + buf = g_malloc0 (37); + uuid_generate_random (uuid); + uuid_unparse_lower (uuid, &buf[0]); + return buf; +} + +/** + * nm_utils_uuid_generate_from_string: + * @s: a string to use as the seed for the UUID + * + * For a given @s, this function will always return the same UUID. + * + * Returns: a newly allocated UUID suitable for use as the #NMSettingConnection + * object's #NMSettingConnection:id: property + **/ +char * +nm_utils_uuid_generate_from_string (const char *s) +{ + GError *error = NULL; + uuid_t *uuid; + char *buf = NULL; + + if (!nm_utils_init (&error)) { + nm_warning ("error initializing crypto: (%d) %s", + error ? error->code : 0, + error ? error->message : "unknown"); + if (error) + g_error_free (error); + return NULL; + } + + uuid = g_malloc0 (sizeof (*uuid)); + if (!crypto_md5_hash (NULL, 0, s, strlen (s), (char *) uuid, sizeof (*uuid), &error)) { + nm_warning ("error generating UUID: (%d) %s", + error ? error->code : 0, + error ? error->message : "unknown"); + if (error) + g_error_free (error); + goto out; + } + + buf = g_malloc0 (37); + uuid_unparse_lower (*uuid, &buf[0]); + +out: + g_free (uuid); + return buf; +} + +static char * +make_key (const char *salt, + const gsize salt_len, + const char *password, + gsize *out_len, + GError **error) +{ + char *key; + guint32 digest_len = 24; /* DES-EDE3-CBC */ + + g_return_val_if_fail (salt != NULL, NULL); + g_return_val_if_fail (salt_len >= 8, NULL); + g_return_val_if_fail (password != NULL, NULL); + g_return_val_if_fail (out_len != NULL, NULL); + + key = g_malloc0 (digest_len + 1); + if (!key) { + g_set_error (error, + NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Not enough memory to make encryption key.")); + return NULL; + } + + if (!crypto_md5_hash (salt, salt_len, password, strlen (password), key, digest_len, error)) { + *out_len = 0; + memset (key, 0, digest_len); + g_free (key); + key = NULL; + } else + *out_len = digest_len; + + return key; +} + +/* + * utils_bin2hexstr + * + * Convert a byte-array into a hexadecimal string. + * + * Code originally by Alex Larsson <alexl@redhat.com> and + * copyright Red Hat, Inc. under terms of the LGPL. + * + */ +static char * +utils_bin2hexstr (const char *bytes, int len, int final_len) +{ + static char hex_digits[] = "0123456789abcdef"; + char *result; + int i; + gsize buflen = (len * 2) + 1; + + g_return_val_if_fail (bytes != NULL, NULL); + g_return_val_if_fail (len > 0, NULL); + g_return_val_if_fail (len < 4096, NULL); /* Arbitrary limit */ + if (final_len > -1) + g_return_val_if_fail (final_len < buflen, NULL); + + result = g_malloc0 (buflen); + for (i = 0; i < len; i++) + { + result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf]; + result[2*i+1] = hex_digits[bytes[i] & 0xf]; + } + /* Cut converted key off at the correct length for this cipher type */ + if (final_len > -1) + result[final_len] = '\0'; + else + result[buflen - 1] = '\0'; + + return result; +} + +/** + * nm_utils_rsa_key_encrypt: + * @data: RSA private key data to be encrypted + * @in_password: existing password to use, if any + * @out_password: if @in_password was NULL, a random password will be generated + * and returned in this argument + * @error: detailed error information on return, if an error occurred + * + * Encrypts the given RSA private key data with the given password (or generates + * a password if no password was given) and converts the data to PEM format + * suitable for writing to a file. + * + * Returns: on success, PEM-formatted data suitable for writing to a PEM-formatted + * certificate/private key file. + **/ +GByteArray * +nm_utils_rsa_key_encrypt (const GByteArray *data, + const char *in_password, + char **out_password, + GError **error) +{ + char salt[8]; + char *key = NULL, *enc = NULL, *pw_buf[32]; + gsize key_len = 0, enc_len = 0; + GString *pem = NULL; + char *tmp, *tmp_password = NULL; + int left; + const char *p; + GByteArray *ret = NULL; + + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->len > 0, NULL); + if (out_password) + g_return_val_if_fail (*out_password == NULL, NULL); + + /* Make the password if needed */ + if (!in_password) { + if (!crypto_randomize (pw_buf, sizeof (pw_buf), error)) + return NULL; + in_password = tmp_password = utils_bin2hexstr ((const char *) pw_buf, sizeof (pw_buf), -1); + } + + if (!crypto_randomize (salt, sizeof (salt), error)) + goto out; + + key = make_key (&salt[0], sizeof (salt), in_password, &key_len, error); + if (!key) + goto out; + + enc = crypto_encrypt (CIPHER_DES_EDE3_CBC, data, salt, sizeof (salt), key, key_len, &enc_len, error); + if (!enc) + goto out; + + pem = g_string_sized_new (enc_len * 2 + 100); + if (!pem) { + g_set_error_literal (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Could not allocate memory for PEM file creation.")); + goto out; + } + + g_string_append (pem, "-----BEGIN RSA PRIVATE KEY-----\n"); + g_string_append (pem, "Proc-Type: 4,ENCRYPTED\n"); + + /* Convert the salt to a hex string */ + tmp = utils_bin2hexstr ((const char *) salt, sizeof (salt), 16); + if (!tmp) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Could not allocate memory for writing IV to PEM file.")); + goto out; + } + + g_string_append_printf (pem, "DEK-Info: DES-EDE3-CBC,%s\n\n", tmp); + g_free (tmp); + + /* Convert the encrypted key to a base64 string */ + p = tmp = g_base64_encode ((const guchar *) enc, enc_len); + if (!tmp) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Could not allocate memory for writing encrypted key to PEM file.")); + goto out; + } + + left = strlen (tmp); + while (left > 0) { + g_string_append_len (pem, p, (left < 64) ? left : 64); + g_string_append_c (pem, '\n'); + left -= 64; + p += 64; + } + g_free (tmp); + + g_string_append (pem, "-----END RSA PRIVATE KEY-----\n"); + + ret = g_byte_array_sized_new (pem->len); + if (!ret) { + g_set_error (error, NM_CRYPTO_ERROR, + NM_CRYPTO_ERR_OUT_OF_MEMORY, + _("Could not allocate memory for PEM file data.")); + goto out; + } + g_byte_array_append (ret, (const unsigned char *) pem->str, pem->len); + if (tmp_password && out_password) + *out_password = g_strdup (tmp_password); + +out: + if (key) { + memset (key, 0, key_len); + g_free (key); + } + if (enc) { + memset (enc, 0, enc_len); + g_free (enc); + } + if (pem) + g_string_free (pem, TRUE); + + if (tmp_password) { + memset (tmp_password, 0, strlen (tmp_password)); + g_free (tmp_password); + } + + return ret; +} + diff --git a/libnm-util/nm-utils.h b/libnm-util/nm-utils.h new file mode 100644 index 00000000..68501d53 --- /dev/null +++ b/libnm-util/nm-utils.h @@ -0,0 +1,218 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * Ray Strode <rstrode@redhat.com> + * Dan Williams <dcbw@redhat.com> + * Tambet Ingo <tambet@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2005 - 2010 Red Hat, Inc. + */ + +#ifndef NM_UTILS_H +#define NM_UTILS_H + +#include <glib.h> +#include <execinfo.h> + +#include "nm-connection.h" + +G_BEGIN_DECLS + +/*********************************************************/ +/* The API defined here is _NOT_ guaranteed in any way!! */ +/*********************************************************/ + +/** + * nm_print_backtrace: + * + * Prints a backtrace of the calling process to the logging location. + */ +#define nm_print_backtrace() \ +G_STMT_START \ +{ \ + void *_call_stack[512]; \ + int _call_stack_size; \ + char **_symbols; \ + _call_stack_size = backtrace (_call_stack, \ + G_N_ELEMENTS (_call_stack)); \ + _symbols = backtrace_symbols (_call_stack, _call_stack_size); \ + if (_symbols != NULL) \ + { \ + int _i; \ + _i = 0; \ + g_critical ("traceback:\n"); \ + while (_i < _call_stack_size) \ + { \ + g_critical ("\t%s\n", _symbols[_i]); \ + _i++; \ + } \ + free (_symbols); \ + } \ +} \ +G_STMT_END + +/** + * nm_get_timestamp: + * @timestamp: location in which to place the current timestamp + * + * For debugging only. + */ +#define nm_get_timestamp(timestamp) \ +G_STMT_START \ +{ \ + GTimeVal _tv; \ + g_get_current_time (&_tv); \ + *timestamp = (_tv.tv_sec * (1.0 * G_USEC_PER_SEC) + \ + _tv.tv_usec) / G_USEC_PER_SEC; \ +} \ +G_STMT_END + +#define nm_info(fmt, args...) \ +G_STMT_START \ +{ \ + g_message ("<info> " fmt "\n", ##args); \ +} G_STMT_END + +#define nm_info_str(fmt_str, args...) \ +G_STMT_START \ +{ \ + g_message ("<info> %s\n", fmt_str, ##args); \ +} G_STMT_END + +#define nm_debug(fmt, args...) \ +G_STMT_START \ +{ \ + gdouble _timestamp; \ + nm_get_timestamp (&_timestamp); \ + g_debug ("<debug> [%f] %s(): " fmt "\n", _timestamp, \ + G_STRFUNC, ##args); \ +} G_STMT_END + +#define nm_debug_str(fmt_str, args...) \ +G_STMT_START \ +{ \ + gdouble _timestamp; \ + nm_get_timestamp (&_timestamp); \ + g_debug ("<debug> [%f] %s(): %s\n", _timestamp, \ + G_STRFUNC, fmt_str, ##args); \ +} G_STMT_END + +#define nm_warning(fmt, args...) \ +G_STMT_START \ +{ \ + g_warning ("<WARN> %s(): " fmt "\n", \ + G_STRFUNC, ##args); \ +} G_STMT_END + +#define nm_warning_str(fmt_str, args...) \ +G_STMT_START \ +{ \ + g_warning ("<WARN> %s(): %s\n", \ + G_STRFUNC, fmt_str, ##args); \ +} G_STMT_END + +#define nm_error(fmt, args...) \ +G_STMT_START \ +{ \ + gdouble _timestamp; \ + nm_get_timestamp (&_timestamp); \ + g_critical ("<ERROR>\t[%f] %s (): " fmt "\n", _timestamp, \ + G_STRFUNC, ##args); \ + nm_print_backtrace (); \ + G_BREAKPOINT (); \ +} G_STMT_END + +#define nm_error_str(fmt_str, args...) \ +G_STMT_START \ +{ \ + gdouble _timestamp; \ + nm_get_timestamp (&_timestamp); \ + g_critical ("<ERROR>\t[%f] %s (): %s\n", _timestamp, \ + G_STRFUNC, fmt_str, ##args); \ + nm_print_backtrace (); \ + G_BREAKPOINT (); \ +} G_STMT_END + +/* init, deinit nm_utils */ +gboolean nm_utils_init (GError **error); +void nm_utils_deinit (void); + +/* SSID helpers */ +gboolean nm_utils_is_empty_ssid (const guint8 * ssid, int len); +const char *nm_utils_escape_ssid (const guint8 *ssid, guint32 len); +gboolean nm_utils_same_ssid (const GByteArray * ssid1, + const GByteArray * ssid2, + gboolean ignore_trailing_null); + +char *nm_utils_ssid_to_utf8 (const char *ssid, guint32 len); + +GHashTable *nm_utils_gvalue_hash_dup (GHashTable *hash); + +void nm_utils_slist_free (GSList *list, + GDestroyNotify elem_destroy_fn); + +typedef enum { + NMU_SEC_INVALID = 0, + NMU_SEC_NONE, + NMU_SEC_STATIC_WEP, + NMU_SEC_LEAP, + NMU_SEC_DYNAMIC_WEP, + NMU_SEC_WPA_PSK, + NMU_SEC_WPA_ENTERPRISE, + NMU_SEC_WPA2_PSK, + NMU_SEC_WPA2_ENTERPRISE +} NMUtilsSecurityType; + +gboolean nm_utils_security_valid (NMUtilsSecurityType type, + guint32 wifi_caps, + gboolean have_ap, + gboolean adhoc, + guint32 ap_flags, + guint32 ap_wpa, + guint32 ap_rsn); + +GSList *nm_utils_ip4_addresses_from_gvalue (const GValue *value); +void nm_utils_ip4_addresses_to_gvalue (GSList *list, GValue *value); + +GSList *nm_utils_ip4_routes_from_gvalue (const GValue *value); +void nm_utils_ip4_routes_to_gvalue (GSList *list, GValue *value); + +guint32 nm_utils_ip4_netmask_to_prefix (guint32 netmask); +guint32 nm_utils_ip4_prefix_to_netmask (guint32 prefix); +guint32 nm_utils_ip4_get_default_prefix (guint32 ip); + +GSList *nm_utils_ip6_addresses_from_gvalue (const GValue *value); +void nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value); + +GSList *nm_utils_ip6_routes_from_gvalue (const GValue *value); +void nm_utils_ip6_routes_to_gvalue (GSList *list, GValue *value); + +GSList *nm_utils_ip6_dns_from_gvalue (const GValue *value); +void nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value); + +char *nm_utils_uuid_generate (void); +char *nm_utils_uuid_generate_from_string (const char *s); + +GByteArray *nm_utils_rsa_key_encrypt (const GByteArray *data, + const char *in_password, + char **out_password, + GError **error); + +G_END_DECLS + +#endif /* NM_UTILS_H */ diff --git a/libnm-util/tests/Makefile.am b/libnm-util/tests/Makefile.am new file mode 100644 index 00000000..378a7388 --- /dev/null +++ b/libnm-util/tests/Makefile.am @@ -0,0 +1,139 @@ +SUBDIRS=certs + +INCLUDES = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/libnm-util + +noinst_PROGRAMS = \ + test-settings-defaults \ + test-crypto \ + test-need-secrets \ + test-general \ + test-setting-8021x + +test_settings_defaults_SOURCES = \ + test-settings-defaults.c + +test_settings_defaults_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +test_settings_defaults_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) \ + $(DBUS_LIBS) + +test_crypto_SOURCES = \ + test-crypto.c + +test_crypto_CPPFLAGS = \ + $(GLIB_CFLAGS) + +test_crypto_LDADD = \ + $(top_builddir)/libnm-util/libtest-crypto.la \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) + +test_need_secrets_SOURCES = \ + test-need-secrets.c + +test_need_secrets_CPPFLAGS = \ + -DTEST_CERT_DIR=\"$(top_srcdir)/libnm-util/tests/certs/\" \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +test_need_secrets_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) \ + $(DBUS_LIBS) + +test_general_SOURCES = \ + test-general.c + +test_general_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +test_general_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) \ + $(DBUS_LIBS) + +test_setting_8021x_SOURCES = \ + test-setting-8021x.c + +test_setting_8021x_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +test_setting_8021x_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) \ + $(DBUS_LIBS) + +if WITH_TESTS + +check-local: test-settings-defaults test-crypto test-need-secrets + $(abs_builddir)/test-settings-defaults + $(abs_builddir)/test-need-secrets + $(abs_builddir)/test-general + +# Private key and CA certificate in the same file (PEM) + $(abs_builddir)/test-setting-8021x \ + $(top_srcdir)/libnm-util/tests/certs/test_key_and_cert.pem \ + "test" \ + $(top_srcdir)/libnm-util/tests/certs/test-key-only-decrypted.der + +# Private key by itself (PEM) + $(abs_builddir)/test-setting-8021x \ + $(top_srcdir)/libnm-util/tests/certs/test-key-only.pem \ + "test" \ + $(top_srcdir)/libnm-util/tests/certs/test-key-only-decrypted.der + +# Private key and CA certificate in the same file (pkcs12) + $(abs_builddir)/test-setting-8021x \ + $(top_srcdir)/libnm-util/tests/certs/test-cert.p12 \ + "test" + +# Normal CA certificate + $(abs_builddir)/test-crypto --cert \ + $(top_srcdir)/libnm-util/tests/certs/test_ca_cert.pem + +# Another CA certificate + $(abs_builddir)/test-crypto --cert \ + $(top_srcdir)/libnm-util/tests/certs/test2_ca_cert.pem + +# CA certificate without an ending newline + $(abs_builddir)/test-crypto --cert \ + $(top_srcdir)/libnm-util/tests/certs/ca-no-ending-newline.pem + +# Combined user cert and private key + $(abs_builddir)/test-crypto --cert \ + $(top_srcdir)/libnm-util/tests/certs/test_key_and_cert.pem + +# Another combined user cert and private key + $(abs_builddir)/test-crypto --cert \ + $(top_srcdir)/libnm-util/tests/certs/test2_key_and_cert.pem + +# Private key with 8 bytes of tail padding + $(abs_builddir)/test-crypto --key \ + $(top_srcdir)/libnm-util/tests/certs/test_key_and_cert.pem \ + "test" + +# Private key with 6 bytes of tail padding + $(abs_builddir)/test-crypto --key \ + $(top_srcdir)/libnm-util/tests/certs/test2_key_and_cert.pem \ + "12345testing" + +# PKCS#12 file + $(abs_builddir)/test-crypto --p12 \ + $(top_srcdir)/libnm-util/tests/certs/test-cert.p12 \ + "test" + +# Another PKCS#12 file + $(abs_builddir)/test-crypto --p12 \ + $(top_srcdir)/libnm-util/tests/certs/test2-cert.p12 \ + "12345testing" + +endif + diff --git a/libnm-util/tests/Makefile.in b/libnm-util/tests/Makefile.in new file mode 100644 index 00000000..9654a565 --- /dev/null +++ b/libnm-util/tests/Makefile.in @@ -0,0 +1,935 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-settings-defaults$(EXEEXT) test-crypto$(EXEEXT) \ + test-need-secrets$(EXEEXT) test-general$(EXEEXT) \ + test-setting-8021x$(EXEEXT) +subdir = libnm-util/tests +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_test_crypto_OBJECTS = test_crypto-test-crypto.$(OBJEXT) +test_crypto_OBJECTS = $(am_test_crypto_OBJECTS) +am__DEPENDENCIES_1 = +test_crypto_DEPENDENCIES = \ + $(top_builddir)/libnm-util/libtest-crypto.la \ + $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) +am_test_general_OBJECTS = test_general-test-general.$(OBJEXT) +test_general_OBJECTS = $(am_test_general_OBJECTS) +test_general_DEPENDENCIES = $(top_builddir)/libnm-util/libnm-util.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_test_need_secrets_OBJECTS = \ + test_need_secrets-test-need-secrets.$(OBJEXT) +test_need_secrets_OBJECTS = $(am_test_need_secrets_OBJECTS) +test_need_secrets_DEPENDENCIES = \ + $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_test_setting_8021x_OBJECTS = \ + test_setting_8021x-test-setting-8021x.$(OBJEXT) +test_setting_8021x_OBJECTS = $(am_test_setting_8021x_OBJECTS) +test_setting_8021x_DEPENDENCIES = \ + $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am_test_settings_defaults_OBJECTS = \ + test_settings_defaults-test-settings-defaults.$(OBJEXT) +test_settings_defaults_OBJECTS = $(am_test_settings_defaults_OBJECTS) +test_settings_defaults_DEPENDENCIES = \ + $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(test_crypto_SOURCES) $(test_general_SOURCES) \ + $(test_need_secrets_SOURCES) $(test_setting_8021x_SOURCES) \ + $(test_settings_defaults_SOURCES) +DIST_SOURCES = $(test_crypto_SOURCES) $(test_general_SOURCES) \ + $(test_need_secrets_SOURCES) $(test_setting_8021x_SOURCES) \ + $(test_settings_defaults_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISABLE_DEPRECATED = @DISABLE_DEPRECATED@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GMODULE_CFLAGS = @GMODULE_CFLAGS@ +GMODULE_LIBS = @GMODULE_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +IPTABLES_PATH = @IPTABLES_PATH@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBM = @LIBM@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POFILES = @POFILES@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +RANLIB = @RANLIB@ +RESOLVCONF_PATH = @RESOLVCONF_PATH@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = certs +INCLUDES = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/libnm-util + +test_settings_defaults_SOURCES = \ + test-settings-defaults.c + +test_settings_defaults_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +test_settings_defaults_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) \ + $(DBUS_LIBS) + +test_crypto_SOURCES = \ + test-crypto.c + +test_crypto_CPPFLAGS = \ + $(GLIB_CFLAGS) + +test_crypto_LDADD = \ + $(top_builddir)/libnm-util/libtest-crypto.la \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) + +test_need_secrets_SOURCES = \ + test-need-secrets.c + +test_need_secrets_CPPFLAGS = \ + -DTEST_CERT_DIR=\"$(top_srcdir)/libnm-util/tests/certs/\" \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +test_need_secrets_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) \ + $(DBUS_LIBS) + +test_general_SOURCES = \ + test-general.c + +test_general_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +test_general_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) \ + $(DBUS_LIBS) + +test_setting_8021x_SOURCES = \ + test-setting-8021x.c + +test_setting_8021x_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(DBUS_CFLAGS) + +test_setting_8021x_LDADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) \ + $(DBUS_LIBS) + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libnm-util/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libnm-util/tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +test-crypto$(EXEEXT): $(test_crypto_OBJECTS) $(test_crypto_DEPENDENCIES) + @rm -f test-crypto$(EXEEXT) + $(LINK) $(test_crypto_OBJECTS) $(test_crypto_LDADD) $(LIBS) +test-general$(EXEEXT): $(test_general_OBJECTS) $(test_general_DEPENDENCIES) + @rm -f test-general$(EXEEXT) + $(LINK) $(test_general_OBJECTS) $(test_general_LDADD) $(LIBS) +test-need-secrets$(EXEEXT): $(test_need_secrets_OBJECTS) $(test_need_secrets_DEPENDENCIES) + @rm -f test-need-secrets$(EXEEXT) + $(LINK) $(test_need_secrets_OBJECTS) $(test_need_secrets_LDADD) $(LIBS) +test-setting-8021x$(EXEEXT): $(test_setting_8021x_OBJECTS) $(test_setting_8021x_DEPENDENCIES) + @rm -f test-setting-8021x$(EXEEXT) + $(LINK) $(test_setting_8021x_OBJECTS) $(test_setting_8021x_LDADD) $(LIBS) +test-settings-defaults$(EXEEXT): $(test_settings_defaults_OBJECTS) $(test_settings_defaults_DEPENDENCIES) + @rm -f test-settings-defaults$(EXEEXT) + $(LINK) $(test_settings_defaults_OBJECTS) $(test_settings_defaults_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto-test-crypto.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_general-test-general.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_need_secrets-test-need-secrets.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_setting_8021x-test-setting-8021x.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_settings_defaults-test-settings-defaults.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +test_crypto-test-crypto.o: test-crypto.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_crypto_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_crypto-test-crypto.o -MD -MP -MF $(DEPDIR)/test_crypto-test-crypto.Tpo -c -o test_crypto-test-crypto.o `test -f 'test-crypto.c' || echo '$(srcdir)/'`test-crypto.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_crypto-test-crypto.Tpo $(DEPDIR)/test_crypto-test-crypto.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-crypto.c' object='test_crypto-test-crypto.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_crypto_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_crypto-test-crypto.o `test -f 'test-crypto.c' || echo '$(srcdir)/'`test-crypto.c + +test_crypto-test-crypto.obj: test-crypto.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_crypto_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_crypto-test-crypto.obj -MD -MP -MF $(DEPDIR)/test_crypto-test-crypto.Tpo -c -o test_crypto-test-crypto.obj `if test -f 'test-crypto.c'; then $(CYGPATH_W) 'test-crypto.c'; else $(CYGPATH_W) '$(srcdir)/test-crypto.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_crypto-test-crypto.Tpo $(DEPDIR)/test_crypto-test-crypto.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-crypto.c' object='test_crypto-test-crypto.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_crypto_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_crypto-test-crypto.obj `if test -f 'test-crypto.c'; then $(CYGPATH_W) 'test-crypto.c'; else $(CYGPATH_W) '$(srcdir)/test-crypto.c'; fi` + +test_general-test-general.o: test-general.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_general_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_general-test-general.o -MD -MP -MF $(DEPDIR)/test_general-test-general.Tpo -c -o test_general-test-general.o `test -f 'test-general.c' || echo '$(srcdir)/'`test-general.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_general-test-general.Tpo $(DEPDIR)/test_general-test-general.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-general.c' object='test_general-test-general.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_general_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_general-test-general.o `test -f 'test-general.c' || echo '$(srcdir)/'`test-general.c + +test_general-test-general.obj: test-general.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_general_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_general-test-general.obj -MD -MP -MF $(DEPDIR)/test_general-test-general.Tpo -c -o test_general-test-general.obj `if test -f 'test-general.c'; then $(CYGPATH_W) 'test-general.c'; else $(CYGPATH_W) '$(srcdir)/test-general.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_general-test-general.Tpo $(DEPDIR)/test_general-test-general.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-general.c' object='test_general-test-general.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_general_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_general-test-general.obj `if test -f 'test-general.c'; then $(CYGPATH_W) 'test-general.c'; else $(CYGPATH_W) '$(srcdir)/test-general.c'; fi` + +test_need_secrets-test-need-secrets.o: test-need-secrets.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_need_secrets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_need_secrets-test-need-secrets.o -MD -MP -MF $(DEPDIR)/test_need_secrets-test-need-secrets.Tpo -c -o test_need_secrets-test-need-secrets.o `test -f 'test-need-secrets.c' || echo '$(srcdir)/'`test-need-secrets.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_need_secrets-test-need-secrets.Tpo $(DEPDIR)/test_need_secrets-test-need-secrets.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-need-secrets.c' object='test_need_secrets-test-need-secrets.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_need_secrets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_need_secrets-test-need-secrets.o `test -f 'test-need-secrets.c' || echo '$(srcdir)/'`test-need-secrets.c + +test_need_secrets-test-need-secrets.obj: test-need-secrets.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_need_secrets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_need_secrets-test-need-secrets.obj -MD -MP -MF $(DEPDIR)/test_need_secrets-test-need-secrets.Tpo -c -o test_need_secrets-test-need-secrets.obj `if test -f 'test-need-secrets.c'; then $(CYGPATH_W) 'test-need-secrets.c'; else $(CYGPATH_W) '$(srcdir)/test-need-secrets.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_need_secrets-test-need-secrets.Tpo $(DEPDIR)/test_need_secrets-test-need-secrets.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-need-secrets.c' object='test_need_secrets-test-need-secrets.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_need_secrets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_need_secrets-test-need-secrets.obj `if test -f 'test-need-secrets.c'; then $(CYGPATH_W) 'test-need-secrets.c'; else $(CYGPATH_W) '$(srcdir)/test-need-secrets.c'; fi` + +test_setting_8021x-test-setting-8021x.o: test-setting-8021x.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_setting_8021x_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_setting_8021x-test-setting-8021x.o -MD -MP -MF $(DEPDIR)/test_setting_8021x-test-setting-8021x.Tpo -c -o test_setting_8021x-test-setting-8021x.o `test -f 'test-setting-8021x.c' || echo '$(srcdir)/'`test-setting-8021x.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_setting_8021x-test-setting-8021x.Tpo $(DEPDIR)/test_setting_8021x-test-setting-8021x.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-setting-8021x.c' object='test_setting_8021x-test-setting-8021x.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_setting_8021x_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_setting_8021x-test-setting-8021x.o `test -f 'test-setting-8021x.c' || echo '$(srcdir)/'`test-setting-8021x.c + +test_setting_8021x-test-setting-8021x.obj: test-setting-8021x.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_setting_8021x_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_setting_8021x-test-setting-8021x.obj -MD -MP -MF $(DEPDIR)/test_setting_8021x-test-setting-8021x.Tpo -c -o test_setting_8021x-test-setting-8021x.obj `if test -f 'test-setting-8021x.c'; then $(CYGPATH_W) 'test-setting-8021x.c'; else $(CYGPATH_W) '$(srcdir)/test-setting-8021x.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_setting_8021x-test-setting-8021x.Tpo $(DEPDIR)/test_setting_8021x-test-setting-8021x.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-setting-8021x.c' object='test_setting_8021x-test-setting-8021x.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_setting_8021x_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_setting_8021x-test-setting-8021x.obj `if test -f 'test-setting-8021x.c'; then $(CYGPATH_W) 'test-setting-8021x.c'; else $(CYGPATH_W) '$(srcdir)/test-setting-8021x.c'; fi` + +test_settings_defaults-test-settings-defaults.o: test-settings-defaults.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_settings_defaults_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_settings_defaults-test-settings-defaults.o -MD -MP -MF $(DEPDIR)/test_settings_defaults-test-settings-defaults.Tpo -c -o test_settings_defaults-test-settings-defaults.o `test -f 'test-settings-defaults.c' || echo '$(srcdir)/'`test-settings-defaults.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_settings_defaults-test-settings-defaults.Tpo $(DEPDIR)/test_settings_defaults-test-settings-defaults.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-settings-defaults.c' object='test_settings_defaults-test-settings-defaults.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_settings_defaults_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_settings_defaults-test-settings-defaults.o `test -f 'test-settings-defaults.c' || echo '$(srcdir)/'`test-settings-defaults.c + +test_settings_defaults-test-settings-defaults.obj: test-settings-defaults.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_settings_defaults_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_settings_defaults-test-settings-defaults.obj -MD -MP -MF $(DEPDIR)/test_settings_defaults-test-settings-defaults.Tpo -c -o test_settings_defaults-test-settings-defaults.obj `if test -f 'test-settings-defaults.c'; then $(CYGPATH_W) 'test-settings-defaults.c'; else $(CYGPATH_W) '$(srcdir)/test-settings-defaults.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_settings_defaults-test-settings-defaults.Tpo $(DEPDIR)/test_settings_defaults-test-settings-defaults.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test-settings-defaults.c' object='test_settings_defaults-test-settings-defaults.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_settings_defaults_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_settings_defaults-test-settings-defaults.obj `if test -f 'test-settings-defaults.c'; then $(CYGPATH_W) 'test-settings-defaults.c'; else $(CYGPATH_W) '$(srcdir)/test-settings-defaults.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +@WITH_TESTS_FALSE@check-local: +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \ + ctags-recursive install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am check-local clean clean-generic \ + clean-libtool clean-noinstPROGRAMS ctags ctags-recursive \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am + + +@WITH_TESTS_TRUE@check-local: test-settings-defaults test-crypto test-need-secrets +@WITH_TESTS_TRUE@ $(abs_builddir)/test-settings-defaults +@WITH_TESTS_TRUE@ $(abs_builddir)/test-need-secrets +@WITH_TESTS_TRUE@ $(abs_builddir)/test-general + +# Private key and CA certificate in the same file (PEM) +@WITH_TESTS_TRUE@ $(abs_builddir)/test-setting-8021x \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test_key_and_cert.pem \ +@WITH_TESTS_TRUE@ "test" \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test-key-only-decrypted.der + +# Private key by itself (PEM) +@WITH_TESTS_TRUE@ $(abs_builddir)/test-setting-8021x \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test-key-only.pem \ +@WITH_TESTS_TRUE@ "test" \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test-key-only-decrypted.der + +# Private key and CA certificate in the same file (pkcs12) +@WITH_TESTS_TRUE@ $(abs_builddir)/test-setting-8021x \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test-cert.p12 \ +@WITH_TESTS_TRUE@ "test" + +# Normal CA certificate +@WITH_TESTS_TRUE@ $(abs_builddir)/test-crypto --cert \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test_ca_cert.pem + +# Another CA certificate +@WITH_TESTS_TRUE@ $(abs_builddir)/test-crypto --cert \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test2_ca_cert.pem + +# CA certificate without an ending newline +@WITH_TESTS_TRUE@ $(abs_builddir)/test-crypto --cert \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/ca-no-ending-newline.pem + +# Combined user cert and private key +@WITH_TESTS_TRUE@ $(abs_builddir)/test-crypto --cert \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test_key_and_cert.pem + +# Another combined user cert and private key +@WITH_TESTS_TRUE@ $(abs_builddir)/test-crypto --cert \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test2_key_and_cert.pem + +# Private key with 8 bytes of tail padding +@WITH_TESTS_TRUE@ $(abs_builddir)/test-crypto --key \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test_key_and_cert.pem \ +@WITH_TESTS_TRUE@ "test" + +# Private key with 6 bytes of tail padding +@WITH_TESTS_TRUE@ $(abs_builddir)/test-crypto --key \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test2_key_and_cert.pem \ +@WITH_TESTS_TRUE@ "12345testing" + +# PKCS#12 file +@WITH_TESTS_TRUE@ $(abs_builddir)/test-crypto --p12 \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test-cert.p12 \ +@WITH_TESTS_TRUE@ "test" + +# Another PKCS#12 file +@WITH_TESTS_TRUE@ $(abs_builddir)/test-crypto --p12 \ +@WITH_TESTS_TRUE@ $(top_srcdir)/libnm-util/tests/certs/test2-cert.p12 \ +@WITH_TESTS_TRUE@ "12345testing" + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libnm-util/tests/certs/Makefile.am b/libnm-util/tests/certs/Makefile.am new file mode 100644 index 00000000..4cd8a24b --- /dev/null +++ b/libnm-util/tests/certs/Makefile.am @@ -0,0 +1,20 @@ +# test-cert.p12 created with: +# +# openssl pkcs12 -export \ +# -in test_key_and_cert.pem \ +# -inkey test_key_and_cert.pem \ +# -certfile test_ca_cert.pem \ +# -name "test-pkcs12" \ +# -out test-cert.p12 + +EXTRA_DIST = \ + test_ca_cert.pem \ + test_key_and_cert.pem \ + test-cert.p12 \ + test2_ca_cert.pem \ + test2_key_and_cert.pem \ + test2-cert.p12 \ + ca-no-ending-newline.pem \ + test-key-only.pem \ + test-key-only-decrypted.der + diff --git a/libnm-util/tests/certs/Makefile.in b/libnm-util/tests/certs/Makefile.in new file mode 100644 index 00000000..18e4af87 --- /dev/null +++ b/libnm-util/tests/certs/Makefile.in @@ -0,0 +1,437 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# test-cert.p12 created with: +# +# openssl pkcs12 -export \ +# -in test_key_and_cert.pem \ +# -inkey test_key_and_cert.pem \ +# -certfile test_ca_cert.pem \ +# -name "test-pkcs12" \ +# -out test-cert.p12 +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = libnm-util/tests/certs +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISABLE_DEPRECATED = @DISABLE_DEPRECATED@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GMODULE_CFLAGS = @GMODULE_CFLAGS@ +GMODULE_LIBS = @GMODULE_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +IPTABLES_PATH = @IPTABLES_PATH@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBM = @LIBM@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POFILES = @POFILES@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +RANLIB = @RANLIB@ +RESOLVCONF_PATH = @RESOLVCONF_PATH@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + test_ca_cert.pem \ + test_key_and_cert.pem \ + test-cert.p12 \ + test2_ca_cert.pem \ + test2_key_and_cert.pem \ + test2-cert.p12 \ + ca-no-ending-newline.pem \ + test-key-only.pem \ + test-key-only-decrypted.der + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libnm-util/tests/certs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libnm-util/tests/certs/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libnm-util/tests/certs/ca-no-ending-newline.pem b/libnm-util/tests/certs/ca-no-ending-newline.pem new file mode 100644 index 00000000..664e299a --- /dev/null +++ b/libnm-util/tests/certs/ca-no-ending-newline.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- \ No newline at end of file diff --git a/libnm-util/tests/certs/test-cert.p12 b/libnm-util/tests/certs/test-cert.p12 new file mode 100644 index 00000000..ae4a6830 --- /dev/null +++ b/libnm-util/tests/certs/test-cert.p12 Binary files differdiff --git a/libnm-util/tests/certs/test-key-only-decrypted.der b/libnm-util/tests/certs/test-key-only-decrypted.der new file mode 100644 index 00000000..c8652537 --- /dev/null +++ b/libnm-util/tests/certs/test-key-only-decrypted.der Binary files differdiff --git a/libnm-util/tests/certs/test-key-only.pem b/libnm-util/tests/certs/test-key-only.pem new file mode 100644 index 00000000..5ef530e9 --- /dev/null +++ b/libnm-util/tests/certs/test-key-only.pem @@ -0,0 +1,92 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B29FCA6ECB7C0C48 + +KuRV4sEVQkY0r0E+E81Se2qpm54HeboUMIJcMVqAt/HIeYwpjEzmXHUywXgayA5k +r5Uvru95vymFz80q/rl6i4Mt3ckEQ3/VHmBI4pPj/JeRbiDhqTyLqpB5zMgbuti+ +PsEemlbiaCMZFdJk8rJBWADTkirGbXs5ciLwTJyrJXhkBVTqoHtphSWMELxcrnQj +5bAXZ+rnApWA7LR3yCY1UE0Nj39Yu8lkzDJtbsSXPJVO//OQiGuQRcY6roAUzeS/ +amLdIYqoZm3OF83Ro88XZCIDCG6XjgKoqojtekClVIytB6mHWk+IHhI7DgU/pDBj +yOskzVRMja9ECnqaVX+bmlmJGZBgcd7+XiebCXNY9IAx/ZQDMbDJDoJusvH6npJR +PBgag8QBSzwpFyEP/1LrlyVyggZcGuXDWfUiM2rt2UvLm8QYeT5WGfUI+QwW6JRV +xEz2QwRiPsmj0uK2fXLKHbY0Pv79IMLqgesCAUbndWsi94kjAhpJGa/WfKVb8Dpg +T+mVa2OT0pgewPWJ3h5f47ag27WDJthsIUHAvNZ03uM23DIqDh6o03/B3/4r1Uab +HzsLWhUOzbLihO08qcPk/JqtDVCv579mpgvy7bL2ZsZUzefnmg+ah+1bhLguryZu +Zrt1hTu5WTz27UbYwWNtkxWnWcM9sSF9y+KVwumYhIUGTvg3Jds/jmp/Z5ad8tev +0RQuWmqnXVD51Y92tOXobJH7JwGbQ4GeRNG/UX7DS9Lvb6rPgmmxvGbXMcjEMapB +m5DLjCD7Lz4++sfzhCic3/nL8e8fjoYZmCbL/SpYjGjTrfoNaGYaT0De8MxCSjPf +rNT+ldWFD0oAOTmT0uqOFkeIx3vxczSQUyRfzGOLqtb9mAXk8lvdb8Myb5atfe8f +FNBL5ocz6Szv2AmKmjZE5P6NKSllyryCYl+H2QU0e3OyY8S9aG2aG8fqeVKaA01S +uOOjsK6IKMpkit+VFDP7RWvS8p1FTwTVRdbMZzASW8+D98OHsTlOENtQuuFyvNaN +vPHrbHltTkwDlYVab9UpFr/ZRW3cNJrmcl0hyeCJxk5u8B9UwW6yZmd24hxda2xt +1QjnxfWlX0i5KTmfWFyPmRYt1WH9rdVaH6wqRbGNbMRT7Lez0E/2+LXjFiiEe0Vh +ZuryhyhUXpHY8yyHxFY92XT504Z3wPUaJ1tQxGhdziZ7HcqFT8f4oTNJdBNtzqNw +l63gSTaKUkSB14CBOyR84cqpgSMwZvWZb3RQFYY4GSALWwhnn6PWeRhjWAXPms2v +tRmfEyDUCyPxDarezvS9kUir3XbvnCkoJOrK/lw4a8ygGBCBqRKOdI0SRUf1Nnjm +aZBrKrXHv5vP66fyC7cGMTq35+iiHbE//rRDGPrf9vpmw3ki3FlDMyAXOC5yWDco +0n+cNDyHJDdIW3+3nfZvSgPPMwmTdfNO90X3YczSmMTGjnIuhQMf7FMFmMZOSrqD +u234vYCjIIlph3aVpbzjOqKg3d4nuP9oouyAgRAr+vShgHRmq0jvsAiGH3Q6RqEj +DvkM1NgoloMy5RhKF4hIeaQM/UlgoXrcEx0RGCJHykQcQmVa5cf5EwjrO7b+w2Lg +-----END RSA PRIVATE KEY----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=test, CN=test/emailAddress=test@test.com + Validity + Not Before: Feb 2 02:22:25 2009 GMT + Not After : Jan 31 02:22:25 2019 GMT + Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=test-client, CN=test-client/emailAddress=test-client@test.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ce:d2:e9:fb:f4:a4:ce:66:87:cc:8b:2d:d2:c3: + b8:fa:be:ea:53:08:95:9e:27:4a:04:78:31:a1:36: + d2:e5:42:f5:76:f7:24:71:b8:d3:10:fd:b7:57:86: + 68:29:02:1b:e9:93:2b:af:c0:7e:3d:58:16:34:10: + 25:85:7e:28:2d:42:fc:34:7f:d6:4f:0a:e7:b6:b9: + 40:51:c8:e5:89:60:cd:73:51:63:67:e1:59:36:31: + 5e:d0:87:4b:5d:97:8a:42:22:d3:42:f2:83:62:79: + 84:45:5b:d8:20:97:e2:d1:34:23:5e:ec:bf:8a:41: + 7c:ad:80:50:f3:9b:1c:51:5d:e4:29:1c:c1:c6:7c: + a1:00:70:0f:f6:79:77:03:22:f5:4b:ab:76:ca:20: + ab:e1:4e:53:6c:86:68:e9:d6:0f:6e:95:4b:b5:b5: + cf:d3:6c:d4:73:db:c0:3d:1d:20:20:72:ab:3e:25: + bb:3f:cd:5f:2d:77:fd:d7:0b:a8:eb:0c:73:c0:3f: + 74:27:17:56:cf:31:9a:a9:ed:c1:39:27:c7:aa:e9: + 77:48:f4:6d:56:89:35:5c:79:5b:f6:2f:8c:9f:93: + bc:13:1c:d0:74:5f:30:1b:15:43:71:8e:ff:1a:df: + 65:65:69:c2:8a:5a:ab:04:4a:80:de:20:29:8d:48: + 1c:83 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 34:E9:5C:D8:FC:C7:AF:F7:5D:F4:13:D3:82:1A:CD:52:0F:4A:BB:0B + X509v3 Authority Key Identifier: + keyid:52:33:2E:22:66:79:82:E5:41:2E:8D:3B:B2:E5:CC:FA:BE:99:33:8E + DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=test/CN=test/emailAddress=test@test.com + serial:E6:4C:5C:96:26:5E:D6:D0 + + Signature Algorithm: md5WithRSAEncryption + 88:c4:dd:c5:4a:a6:8e:1f:36:62:80:31:6b:2b:85:34:0d:6c: + a7:dc:e1:5a:3c:dd:74:57:db:59:be:8b:f2:79:40:2d:bd:9b: + e1:ab:0e:03:75:20:75:2f:ea:97:f9:d4:7e:15:75:c2:82:f5: + b1:37:e4:8b:24:d4:ef:02:3b:19:6a:56:bb:9f:c3:a5:b4:c4: + 39:a0:64:96:5b:c3:a8:19:74:ec:0b:cf:33:df:f3:12:f3:e2: + ab:1d:7d:de:21:64:cd:b1:a0:6f:7a:77:84:d4:62:8a:50:e6: + 76:5d:af:3a:ef:1a:87:0e:1a:38:c4:f9:0d:2f:14:e0:20:32: + 4c:2e:70:d2:71:82:d5:e5:c9:13:2c:4e:b4:c8:63:65:1d:48: + e8:c3:56:6d:88:84:57:65:13:1e:42:48:b4:03:25:71:4e:12: + 9d:1a:88:65:d5:71:21:3b:0e:be:37:1c:f0:88:6b:45:0c:0e: + 6c:e5:60:cb:86:bf:bf:40:30:c4:cf:94:f8:1c:60:d4:1b:df: + 88:02:7a:45:7e:d1:c6:f3:07:b9:b1:8f:2a:55:2f:be:77:9f: + d1:46:64:05:b7:67:c5:b2:ac:8c:42:8f:6a:51:a4:0d:2b:16: + a4:d6:39:a5:f8:25:ed:68:25:13:b5:19:ac:6c:e9:ec:ee:03: + 6b:80:38:6e + diff --git a/libnm-util/tests/certs/test2-cert.p12 b/libnm-util/tests/certs/test2-cert.p12 new file mode 100644 index 00000000..9d5732b0 --- /dev/null +++ b/libnm-util/tests/certs/test2-cert.p12 Binary files differdiff --git a/libnm-util/tests/certs/test2_ca_cert.pem b/libnm-util/tests/certs/test2_ca_cert.pem new file mode 100644 index 00000000..9a487ca4 --- /dev/null +++ b/libnm-util/tests/certs/test2_ca_cert.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEpDCCA4ygAwIBAgIJANDnVhixAO1GMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYD +VQQGEwJVUzEWMBQGA1UECBMNTWFzc2FjaHVzZXR0czERMA8GA1UEBxMIV2VzdGZv +cmQxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xFDASBgNVBAsTC0VuZ2luZWVyaW5n +MRAwDgYDVQQDEwdlYXB0ZXN0MRgwFgYJKoZIhvcNAQkBFglpdEBpdC5jb20wHhcN +MDcxMTA5MTU0ODI1WhcNMTcxMTA2MTU0ODI1WjCBkjELMAkGA1UEBhMCVVMxFjAU +BgNVBAgTDU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQK +Ew1SZWQgSGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UEAxMH +ZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAz9zRLSiQyQangDgEliEP8xSpnPJS7GjXzrkZS3sk +gZLuVuwoFeZRq3Hsrq/wGd/vM0KUFNmEaMc+47jnuv0UHQcQ45ZACO7s4/Aflhzj +lkmud/z06hVknIzjXmvS6q2ttCviHsXnfokl+wAxuUhsd+le0xjP9H1jXny4YBuS +jP+yGUz7PL4w1sFFghKIPrlB7m4GkFbQRqvH7FSJg86GWopPwJvNvIzhOZiO1a1D +CAAL4Ru3jxtNFxqWT87C/qUEe/2Qb7jtNyqFcKfwZyZh4u1bo0c8bjErlUZERbWz +zM3hTFypuw+i2v+0h3A8/Xb0hTjcHkUoJgfSdbsOLC5TOwIDAQABo4H6MIH3MB0G +A1UdDgQWBBR+UOaH4e8nrEuMcEXJl7UN5r/wDTCBxwYDVR0jBIG/MIG8gBR+UOaH +4e8nrEuMcEXJl7UN5r/wDaGBmKSBlTCBkjELMAkGA1UEBhMCVVMxFjAUBgNVBAgT +DU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQKEw1SZWQg +SGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UEAxMHZWFwdGVz +dDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tggkA0OdWGLEA7UYwDAYDVR0TBAUw +AwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAmE2jqUymfxN2Vv7bPafoK/EpZwGPxu+z +phRFsgUgWVzidc/GtOxN81LduJ+ow8MEbQIabo4JV/MdKzuPuhAHToAQdeb0LIWa +p59vTIZiVhUt0cMAbQwKcTnfmDnXw9wytvtKgeAXJq0Jd6F+uNXTiR1btlYLZqmF +oSu54cHQlXpUT9z0BnQ8eXd7m0TwfzGQkTHQI7xBa87lZDAkJaTlhv7fR5vPmJYY +0LiXii71ce+4hxdlp7hQfwQ2sb8FPY3RlVboTRD0CvGaWypWhdSZnS790dBXgZOs +NCge6NGuHzW5LtiZE9ppuv8qJysVcIFdAqt8dkx58ksOqFcARCerXw== +-----END CERTIFICATE----- diff --git a/libnm-util/tests/certs/test2_key_and_cert.pem b/libnm-util/tests/certs/test2_key_and_cert.pem new file mode 100644 index 00000000..a668596e --- /dev/null +++ b/libnm-util/tests/certs/test2_key_and_cert.pem @@ -0,0 +1,119 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,5FA2D6D6242C26D0 + +dyNdbh115sczbUEhiaGYJ6fazyvJss5thPFEmkP6aftYlvXY6vPtc++xFCCktiSd +qFVEyi6oDyV4iGPmX7pCJ0e+pSI6uFNXKFtxh5/+/wXZcOEMCvfu7w2IrvYF2LHY +qJDljcISSRxeINuYO7TETD5fLLRKj2X9vwwkwVN02b2N5jsrm6Bt//WbatqSB3ln +FHyQhVKkvdl9Hr1XNmEfgGfZSxxDoPu1DjhtZ5ja2LZj64C2CXdI0oq2wcAVvQNn +rZeeg9sinQJkz9rwsNaWqlYw4X+YD2JRSwZuvwkWRydYMwgb1XS/jCxtuFF8NXWP +RBAOAZZUy7onzohsJHVVa05wCKQ4klo+PEfI3vn7BeuHyciCc0eFqGRvz8eFDybH +ZdPbU/3vGp+mOB7gd27TptttTCQQy9uM5CIyovNSYsAIw1Z583Ea4q8eXgzkgD6D +isCqkGXMfPbNXU3myQGDnQwWRi2CqX+rXM8PJUhdewLAlmHRz/aYSuql2BRixJKx +eASzmFBYdAjrvafda5D+xTyJwXEwdq/HlqMK9cY28ZbNrzA2Kor2X23EKC1+VG8k +B67OsfUhW27j4u6aV5JdLf87OtF3mHFRR+Lzs7i7LYvJ8ACE+jiIi7PboZjK5Oiv +JqTK0BwDaeNYjkd6jiJh8It/ReMbLk65J3eldOklN0VMPYiqcQnHvSPC2DD1YAy+ +Rv/JVj6TvzvgEAj+hgH6MAAF6u3ARj6+10DlvhUubkOC5RztLKReu8B+427TuuDb +T03gFpHD6X9IqSiq/QfYFyHFojCVSrv6wDZOcHc1s71kpJ8R14YIVe+DrrZN/0D4 +M631jdNg3JARMZXcXTHrghGIdPmOtrsRyTTRZuGoVup/DW9MRzOzCTMSNCX8T+eq +13HMSNQEO9lMwy0sYeO5c7sjHY4K1ubZuVE1mvXq4JLz3YxXJIvgp8TUvqDnAsK+ +Fv63bDoTg5Tq63XvnaKc7Lawneyg5ZAMzPN3nM0/1EZcn/2ICI5c4Yepc5t63EI5 +KytuXx86Mcx234enj3uMeuM22POQ1SnKOef6dFzK/CE8J8eUEY/aDhX4eBl/s3nd +U4+aaFKYz3HTazePayt2SC6rP/KKMmS14q59bOQA1DiWxCvmA2ypRyP87fV5DstH +I53RD5xp1P38iaO8U/divD0W2dkv748s9DQqYrHPtWALT9esxNU07CgB8Zt070si +7pzjQ8FDCZ8ygDmwWGNSBz1nA90Cpd6gAFDrep7HAtDE4qgNfokycpaJZkXBei/U +tC4tWYRbqDEsEbeBHvQRJzzqWzk9e/P4fQoelM3aryKzKLG5z7KvywVifKMLECQ+ +tIpzoRp06nuTA/O+iLFdkCy3JEWszfvvOwTwtIIV6+3s8TU0k9MmzEe3rGL+QqT/ +Tf+9/dN5LK+LWyc99BfmCOrBuFtQmHyEXkfe6EuFYEwj0B2ZfnLCon6cdRujjK7H +IJslC1B/cBVqG3KCrbBzjeygKfJ5Ijo72oXZJOCFTLeJefZKGGWJCp9nG9h9Wrcf +fEN/mj3wBvTa90/PYFj9NuaBtrvMF8Rn9XDeYPq2JGL8YkNdPuO8A+2Yko8wcvST +-----END RSA PRIVATE KEY----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Massachusetts, L=Westford, O=Red Hat, Inc., OU=Engineering, CN=eaptest/emailAddress=it@it.com + Validity + Not Before: Nov 9 15:50:14 2007 GMT + Not After : Nov 6 15:50:14 2017 GMT + Subject: C=US, ST=Massachusetts, O=Red Hat, Inc., OU=Engineering, CN=client/emailAddress=it@it.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b0:8f:4f:1c:93:d4:43:e7:87:b7:22:33:55:a8: + 35:a1:c4:01:b0:f1:ed:26:23:96:ab:65:c2:c2:54: + db:79:22:03:ad:3f:6f:22:e3:63:3f:f4:21:6d:fa: + 88:c8:8f:1a:ce:55:49:7c:98:33:6a:67:8a:8d:d9: + 34:b0:c3:42:f4:72:a4:45:43:05:72:5d:0c:d3:42: + f8:9c:66:3b:b8:f8:77:ea:f6:b6:94:d7:cc:5d:62: + 34:2a:14:48:0a:bc:65:94:f5:7a:63:98:6c:88:4c: + 25:d8:95:f1:40:3d:00:d2:fb:43:28:fa:02:fb:2c: + 80:b3:e1:33:e7:8c:ce:8a:a0:1b:3d:04:4d:bc:a1: + b6:a2:42:8b:8e:f3:5b:4a:72:34:7d:8d:ba:d8:46: + 22:35:da:5c:f8:dd:fc:6d:9e:59:22:b7:6b:e7:78: + 56:54:9f:4c:d1:e2:4a:23:a3:bc:04:ea:46:6b:70: + 8a:fb:fe:8a:73:ca:36:d5:f3:e9:17:e3:22:d5:b3: + 70:05:e7:f7:37:b7:21:b5:90:53:27:27:ea:36:9b: + 00:ff:35:b0:66:3d:dc:a9:2f:95:d2:21:18:98:4f: + 28:07:09:70:20:a8:b1:82:aa:a5:df:ae:0f:e3:36: + be:68:8c:9e:80:d3:33:d0:f5:84:17:d9:0f:eb:9d: + af:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 71:AB:BB:91:B7:04:DE:43:35:36:07:8A:35:CA:BE:5C:3E:EB:B1:09 + X509v3 Authority Key Identifier: + keyid:7E:50:E6:87:E1:EF:27:AC:4B:8C:70:45:C9:97:B5:0D:E6:BF:F0:0D + DirName:/C=US/ST=Massachusetts/L=Westford/O=Red Hat, Inc./OU=Engineering/CN=eaptest/emailAddress=it@it.com + serial:D0:E7:56:18:B1:00:ED:46 + + Signature Algorithm: md5WithRSAEncryption + ce:43:6d:f7:f8:4a:66:fd:8a:2c:41:a6:e0:03:0e:60:30:d4: + 41:01:ba:46:ba:81:97:64:68:83:25:9c:e1:2c:03:8b:2d:ca: + 85:cf:bc:fa:ca:22:c4:59:28:23:8f:ff:50:94:60:1c:90:dd: + 75:f4:d4:ea:8c:fa:61:61:08:35:4a:8f:aa:a7:e9:3d:76:e9: + 08:28:55:01:c4:03:42:c7:ad:58:bb:ee:94:f7:09:b3:9a:9b: + 8b:d0:25:95:18:a6:22:d5:2c:fc:b7:bb:91:0c:7c:03:7f:9b: + 85:de:b0:e4:95:a8:73:94:27:0a:11:4e:e3:67:ae:2b:cc:e7: + 51:29:10:23:57:5c:3e:e7:ea:47:e0:f0:8f:5b:a2:9f:26:cf: + 7f:b5:7c:44:b1:7b:83:67:3c:41:ae:c6:66:64:e0:d2:ef:57: + a4:5c:1b:94:11:ce:28:e5:91:51:ef:e1:98:b7:3b:9a:cc:f7: + b9:85:76:eb:a8:2b:15:4a:cc:1a:a3:42:fa:be:1c:ce:b8:eb: + ee:12:d7:2f:e4:a8:cf:eb:2a:8f:78:e8:91:88:fa:c2:98:75: + 6a:4c:92:3f:2e:0d:e1:20:39:36:c6:2c:be:67:30:c3:f3:c3: + 65:81:ac:e3:3c:19:6a:21:ee:ea:f5:22:66:74:b2:07:53:7c: + 9a:0c:24:a6 +-----BEGIN CERTIFICATE----- +MIIEtDCCA5ygAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBkjELMAkGA1UEBhMCVVMx +FjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYD +VQQKEw1SZWQgSGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UE +AxMHZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tMB4XDTA3MTEwOTE1 +NTAxNFoXDTE3MTEwNjE1NTAxNFowfjELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1h +c3NhY2h1c2V0dHMxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xFDASBgNVBAsTC0Vu +Z2luZWVyaW5nMQ8wDQYDVQQDEwZjbGllbnQxGDAWBgkqhkiG9w0BCQEWCWl0QGl0 +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALCPTxyT1EPnh7ci +M1WoNaHEAbDx7SYjlqtlwsJU23kiA60/byLjYz/0IW36iMiPGs5VSXyYM2pnio3Z +NLDDQvRypEVDBXJdDNNC+JxmO7j4d+r2tpTXzF1iNCoUSAq8ZZT1emOYbIhMJdiV +8UA9ANL7Qyj6AvssgLPhM+eMzoqgGz0ETbyhtqJCi47zW0pyNH2NuthGIjXaXPjd +/G2eWSK3a+d4VlSfTNHiSiOjvATqRmtwivv+inPKNtXz6RfjItWzcAXn9ze3IbWQ +Uycn6jabAP81sGY93KkvldIhGJhPKAcJcCCosYKqpd+uD+M2vmiMnoDTM9D1hBfZ +D+udrwsCAwEAAaOCASYwggEiMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w +ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRxq7uRtwTeQzU2 +B4o1yr5cPuuxCTCBxwYDVR0jBIG/MIG8gBR+UOaH4e8nrEuMcEXJl7UN5r/wDaGB +mKSBlTCBkjELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxETAP +BgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQKEw1SZWQgSGF0LCBJbmMuMRQwEgYDVQQL +EwtFbmdpbmVlcmluZzEQMA4GA1UEAxMHZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJ +aXRAaXQuY29tggkA0OdWGLEA7UYwDQYJKoZIhvcNAQEEBQADggEBAM5Dbff4Smb9 +iixBpuADDmAw1EEBuka6gZdkaIMlnOEsA4styoXPvPrKIsRZKCOP/1CUYByQ3XX0 +1OqM+mFhCDVKj6qn6T126QgoVQHEA0LHrVi77pT3CbOam4vQJZUYpiLVLPy3u5EM +fAN/m4XesOSVqHOUJwoRTuNnrivM51EpECNXXD7n6kfg8I9bop8mz3+1fESxe4Nn +PEGuxmZk4NLvV6RcG5QRzijlkVHv4Zi3O5rM97mFduuoKxVKzBqjQvq+HM646+4S +1y/kqM/rKo946JGI+sKYdWpMkj8uDeEgOTbGLL5nMMPzw2WBrOM8GWoh7ur1ImZ0 +sgdTfJoMJKY= +-----END CERTIFICATE----- diff --git a/libnm-util/tests/certs/test_ca_cert.pem b/libnm-util/tests/certs/test_ca_cert.pem new file mode 100644 index 00000000..faa3fc29 --- /dev/null +++ b/libnm-util/tests/certs/test_ca_cert.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEhjCCA26gAwIBAgIJAOZMXJYmXtbQMA0GCSqGSIb3DQEBBQUAMIGIMQswCQYD +VQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcw +FQYDVQQKEw5NeSBDb21wYW55IEx0ZDENMAsGA1UECxMEdGVzdDENMAsGA1UEAxME +dGVzdDEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0wOTAyMDIwMjIx +NTJaFw0xOTAxMzEwMjIxNTJaMIGIMQswCQYDVQQGEwJVUzESMBAGA1UECBMJQmVy +a3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5NeSBDb21wYW55IEx0 +ZDENMAsGA1UECxMEdGVzdDENMAsGA1UEAxMEdGVzdDEcMBoGCSqGSIb3DQEJARYN +dGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANZz +iHfFR6Gqdz5Gq1elSaf7J2tznfialPyMkRoqngSItrM3JWlkfBu3ZIpGSYG8+Z8H +JjaKh/zkCCH73HcjADCocm/XtgxlOlccDtBvfDqifb2dBikcmcfh0tX0o4JU9L+z +WP7sVcUkJG7C5811lA5pAsLVooJxrZnrta6XstGvFgTSxI2Y4Jowf0syM5b/AHIQ ++htsVhSyj1DWM9day3QsEMZl55SCxCLTB6ZIJLF6NmTYwdnzWWTQf4k7kcptZJU8 +Fqv60b/ATvvUf7S+ZMGLopFIIlmc1Kkn7VTseIKy4ycYuDpyimQy3Yw4flC00vhl +hTijH+5dlVOUFrRh0bsCAwEAAaOB8DCB7TAdBgNVHQ4EFgQUUjMuImZ5guVBLo07 +suXM+r6ZM44wgb0GA1UdIwSBtTCBsoAUUjMuImZ5guVBLo07suXM+r6ZM46hgY6k +gYswgYgxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcT +B05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMQ0wCwYDVQQLEwR0ZXN0 +MQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3QuY29tggkA +5kxcliZe1tAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAZsWzGp9D +10NWf8ts3A9mhcEb8oDgKNpCOZF9gqr2usZygJjY9MX2n0n81T8XaWDk1wZLlcDW +hzIalCY8rpE57Dj3MEmdCmYr3BrAy6GVlc/MO7ffTHxogl9ouScSYo8ETTtNMKCg +zwkDnXjGzmb1e59DIXMVHBBbTmJXJbM8XP9A2azJkVUyE2fSdWksXMP0XklGbW2p +DksJ+8G1IWkyRhnINV5GZLLNAT5gBA6sUv/iqQKwk8r2dsweMPtLoLWZPAaZErYh +sthGy00Q0GJkmkJpQl8QIlPq5vylNcMUhvc8tmzwk+rDVUj3jTJWqFwMtnHAaNyC +FXl9ynWpe5J28w== +-----END CERTIFICATE----- diff --git a/libnm-util/tests/certs/test_key_and_cert.pem b/libnm-util/tests/certs/test_key_and_cert.pem new file mode 100644 index 00000000..c00495d0 --- /dev/null +++ b/libnm-util/tests/certs/test_key_and_cert.pem @@ -0,0 +1,119 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B29FCA6ECB7C0C48 + +KuRV4sEVQkY0r0E+E81Se2qpm54HeboUMIJcMVqAt/HIeYwpjEzmXHUywXgayA5k +r5Uvru95vymFz80q/rl6i4Mt3ckEQ3/VHmBI4pPj/JeRbiDhqTyLqpB5zMgbuti+ +PsEemlbiaCMZFdJk8rJBWADTkirGbXs5ciLwTJyrJXhkBVTqoHtphSWMELxcrnQj +5bAXZ+rnApWA7LR3yCY1UE0Nj39Yu8lkzDJtbsSXPJVO//OQiGuQRcY6roAUzeS/ +amLdIYqoZm3OF83Ro88XZCIDCG6XjgKoqojtekClVIytB6mHWk+IHhI7DgU/pDBj +yOskzVRMja9ECnqaVX+bmlmJGZBgcd7+XiebCXNY9IAx/ZQDMbDJDoJusvH6npJR +PBgag8QBSzwpFyEP/1LrlyVyggZcGuXDWfUiM2rt2UvLm8QYeT5WGfUI+QwW6JRV +xEz2QwRiPsmj0uK2fXLKHbY0Pv79IMLqgesCAUbndWsi94kjAhpJGa/WfKVb8Dpg +T+mVa2OT0pgewPWJ3h5f47ag27WDJthsIUHAvNZ03uM23DIqDh6o03/B3/4r1Uab +HzsLWhUOzbLihO08qcPk/JqtDVCv579mpgvy7bL2ZsZUzefnmg+ah+1bhLguryZu +Zrt1hTu5WTz27UbYwWNtkxWnWcM9sSF9y+KVwumYhIUGTvg3Jds/jmp/Z5ad8tev +0RQuWmqnXVD51Y92tOXobJH7JwGbQ4GeRNG/UX7DS9Lvb6rPgmmxvGbXMcjEMapB +m5DLjCD7Lz4++sfzhCic3/nL8e8fjoYZmCbL/SpYjGjTrfoNaGYaT0De8MxCSjPf +rNT+ldWFD0oAOTmT0uqOFkeIx3vxczSQUyRfzGOLqtb9mAXk8lvdb8Myb5atfe8f +FNBL5ocz6Szv2AmKmjZE5P6NKSllyryCYl+H2QU0e3OyY8S9aG2aG8fqeVKaA01S +uOOjsK6IKMpkit+VFDP7RWvS8p1FTwTVRdbMZzASW8+D98OHsTlOENtQuuFyvNaN +vPHrbHltTkwDlYVab9UpFr/ZRW3cNJrmcl0hyeCJxk5u8B9UwW6yZmd24hxda2xt +1QjnxfWlX0i5KTmfWFyPmRYt1WH9rdVaH6wqRbGNbMRT7Lez0E/2+LXjFiiEe0Vh +ZuryhyhUXpHY8yyHxFY92XT504Z3wPUaJ1tQxGhdziZ7HcqFT8f4oTNJdBNtzqNw +l63gSTaKUkSB14CBOyR84cqpgSMwZvWZb3RQFYY4GSALWwhnn6PWeRhjWAXPms2v +tRmfEyDUCyPxDarezvS9kUir3XbvnCkoJOrK/lw4a8ygGBCBqRKOdI0SRUf1Nnjm +aZBrKrXHv5vP66fyC7cGMTq35+iiHbE//rRDGPrf9vpmw3ki3FlDMyAXOC5yWDco +0n+cNDyHJDdIW3+3nfZvSgPPMwmTdfNO90X3YczSmMTGjnIuhQMf7FMFmMZOSrqD +u234vYCjIIlph3aVpbzjOqKg3d4nuP9oouyAgRAr+vShgHRmq0jvsAiGH3Q6RqEj +DvkM1NgoloMy5RhKF4hIeaQM/UlgoXrcEx0RGCJHykQcQmVa5cf5EwjrO7b+w2Lg +-----END RSA PRIVATE KEY----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=test, CN=test/emailAddress=test@test.com + Validity + Not Before: Feb 2 02:22:25 2009 GMT + Not After : Jan 31 02:22:25 2019 GMT + Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=test-client, CN=test-client/emailAddress=test-client@test.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ce:d2:e9:fb:f4:a4:ce:66:87:cc:8b:2d:d2:c3: + b8:fa:be:ea:53:08:95:9e:27:4a:04:78:31:a1:36: + d2:e5:42:f5:76:f7:24:71:b8:d3:10:fd:b7:57:86: + 68:29:02:1b:e9:93:2b:af:c0:7e:3d:58:16:34:10: + 25:85:7e:28:2d:42:fc:34:7f:d6:4f:0a:e7:b6:b9: + 40:51:c8:e5:89:60:cd:73:51:63:67:e1:59:36:31: + 5e:d0:87:4b:5d:97:8a:42:22:d3:42:f2:83:62:79: + 84:45:5b:d8:20:97:e2:d1:34:23:5e:ec:bf:8a:41: + 7c:ad:80:50:f3:9b:1c:51:5d:e4:29:1c:c1:c6:7c: + a1:00:70:0f:f6:79:77:03:22:f5:4b:ab:76:ca:20: + ab:e1:4e:53:6c:86:68:e9:d6:0f:6e:95:4b:b5:b5: + cf:d3:6c:d4:73:db:c0:3d:1d:20:20:72:ab:3e:25: + bb:3f:cd:5f:2d:77:fd:d7:0b:a8:eb:0c:73:c0:3f: + 74:27:17:56:cf:31:9a:a9:ed:c1:39:27:c7:aa:e9: + 77:48:f4:6d:56:89:35:5c:79:5b:f6:2f:8c:9f:93: + bc:13:1c:d0:74:5f:30:1b:15:43:71:8e:ff:1a:df: + 65:65:69:c2:8a:5a:ab:04:4a:80:de:20:29:8d:48: + 1c:83 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 34:E9:5C:D8:FC:C7:AF:F7:5D:F4:13:D3:82:1A:CD:52:0F:4A:BB:0B + X509v3 Authority Key Identifier: + keyid:52:33:2E:22:66:79:82:E5:41:2E:8D:3B:B2:E5:CC:FA:BE:99:33:8E + DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=test/CN=test/emailAddress=test@test.com + serial:E6:4C:5C:96:26:5E:D6:D0 + + Signature Algorithm: md5WithRSAEncryption + 88:c4:dd:c5:4a:a6:8e:1f:36:62:80:31:6b:2b:85:34:0d:6c: + a7:dc:e1:5a:3c:dd:74:57:db:59:be:8b:f2:79:40:2d:bd:9b: + e1:ab:0e:03:75:20:75:2f:ea:97:f9:d4:7e:15:75:c2:82:f5: + b1:37:e4:8b:24:d4:ef:02:3b:19:6a:56:bb:9f:c3:a5:b4:c4: + 39:a0:64:96:5b:c3:a8:19:74:ec:0b:cf:33:df:f3:12:f3:e2: + ab:1d:7d:de:21:64:cd:b1:a0:6f:7a:77:84:d4:62:8a:50:e6: + 76:5d:af:3a:ef:1a:87:0e:1a:38:c4:f9:0d:2f:14:e0:20:32: + 4c:2e:70:d2:71:82:d5:e5:c9:13:2c:4e:b4:c8:63:65:1d:48: + e8:c3:56:6d:88:84:57:65:13:1e:42:48:b4:03:25:71:4e:12: + 9d:1a:88:65:d5:71:21:3b:0e:be:37:1c:f0:88:6b:45:0c:0e: + 6c:e5:60:cb:86:bf:bf:40:30:c4:cf:94:f8:1c:60:d4:1b:df: + 88:02:7a:45:7e:d1:c6:f3:07:b9:b1:8f:2a:55:2f:be:77:9f: + d1:46:64:05:b7:67:c5:b2:ac:8c:42:8f:6a:51:a4:0d:2b:16: + a4:d6:39:a5:f8:25:ed:68:25:13:b5:19:ac:6c:e9:ec:ee:03: + 6b:80:38:6e +-----BEGIN CERTIFICATE----- +MIIErjCCA5agAwIBAgIBATANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCVVMx +EjAQBgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMO +TXkgQ29tcGFueSBMdGQxDTALBgNVBAsTBHRlc3QxDTALBgNVBAMTBHRlc3QxHDAa +BgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wHhcNMDkwMjAyMDIyMjI1WhcNMTkw +MTMxMDIyMjI1WjCBizELMAkGA1UEBhMCVVMxEjAQBgNVBAgTCUJlcmtzaGlyZTEX +MBUGA1UEChMOTXkgQ29tcGFueSBMdGQxFDASBgNVBAsTC3Rlc3QtY2xpZW50MRQw +EgYDVQQDEwt0ZXN0LWNsaWVudDEjMCEGCSqGSIb3DQEJARYUdGVzdC1jbGllbnRA +dGVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO0un79KTO +ZofMiy3Sw7j6vupTCJWeJ0oEeDGhNtLlQvV29yRxuNMQ/bdXhmgpAhvpkyuvwH49 +WBY0ECWFfigtQvw0f9ZPCue2uUBRyOWJYM1zUWNn4Vk2MV7Qh0tdl4pCItNC8oNi +eYRFW9ggl+LRNCNe7L+KQXytgFDzmxxRXeQpHMHGfKEAcA/2eXcDIvVLq3bKIKvh +TlNshmjp1g9ulUu1tc/TbNRz28A9HSAgcqs+Jbs/zV8td/3XC6jrDHPAP3QnF1bP +MZqp7cE5J8eq6XdI9G1WiTVceVv2L4yfk7wTHNB0XzAbFUNxjv8a32VlacKKWqsE +SoDeICmNSByDAgMBAAGjggEcMIIBGDAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf +Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUNOlc2PzH +r/dd9BPTghrNUg9Kuwswgb0GA1UdIwSBtTCBsoAUUjMuImZ5guVBLo07suXM+r6Z +M46hgY6kgYswgYgxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAO +BgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMQ0wCwYDVQQL +EwR0ZXN0MQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3Qu +Y29tggkA5kxcliZe1tAwDQYJKoZIhvcNAQEEBQADggEBAIjE3cVKpo4fNmKAMWsr +hTQNbKfc4Vo83XRX21m+i/J5QC29m+GrDgN1IHUv6pf51H4VdcKC9bE35Isk1O8C +OxlqVrufw6W0xDmgZJZbw6gZdOwLzzPf8xLz4qsdfd4hZM2xoG96d4TUYopQ5nZd +rzrvGocOGjjE+Q0vFOAgMkwucNJxgtXlyRMsTrTIY2UdSOjDVm2IhFdlEx5CSLQD +JXFOEp0aiGXVcSE7Dr43HPCIa0UMDmzlYMuGv79AMMTPlPgcYNQb34gCekV+0cbz +B7mxjypVL753n9FGZAW3Z8WyrIxCj2pRpA0rFqTWOaX4Je1oJRO1Gaxs6ezuA2uA +OG4= +-----END CERTIFICATE----- diff --git a/libnm-util/tests/test-crypto.c b/libnm-util/tests/test-crypto.c new file mode 100644 index 00000000..a5466bc8 --- /dev/null +++ b/libnm-util/tests/test-crypto.c @@ -0,0 +1,317 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * Dan Williams <dcbw@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2009 Red Hat, Inc. + */ + +#include <glib.h> +#include <unistd.h> +#include <stdlib.h> +#include <glib/gi18n.h> +#include <stdio.h> +#include <string.h> + +#include "nm-test-helpers.h" +#include "crypto.h" +#include "nm-utils.h" + +#if 0 +static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; +static const char *pem_rsa_key_end = "-----END RSA PRIVATE KEY-----"; + +static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----"; +static const char *pem_dsa_key_end = "-----END DSA PRIVATE KEY-----"; + +static void +dump_key_to_pem (const char *key, gsize key_len, int key_type) +{ + char *b64 = NULL; + GString *str = NULL; + const char *start_tag; + const char *end_tag; + char *p; + + switch (key_type) { + case NM_CRYPTO_KEY_TYPE_RSA: + start_tag = pem_rsa_key_begin; + end_tag = pem_rsa_key_end; + break; + case NM_CRYPTO_KEY_TYPE_DSA: + start_tag = pem_dsa_key_begin; + end_tag = pem_dsa_key_end; + break; + default: + g_warning ("Unknown key type %d", key_type); + return; + } + + b64 = g_base64_encode ((const unsigned char *) key, key_len); + if (!b64) { + g_warning ("Couldn't base64 encode the key."); + goto out; + } + + str = g_string_new (NULL); + if (!str) { + g_warning ("Couldn't allocate buffer to write out key."); + goto out; + } + + g_string_append (str, start_tag); + g_string_append_c (str, '\n'); + + for (p = b64; p < (b64 + strlen (b64)); p += 64) { + g_string_append_len (str, p, strnlen (p, 64)); + g_string_append_c (str, '\n'); + } + + g_string_append (str, end_tag); + g_string_append_c (str, '\n'); + + g_message ("Decrypted private key:\n\n%s", str->str); + +out: + g_free (b64); + if (str) + g_string_free (str, TRUE); +} +#endif + +static void +test_load_cert (const char *path, const char *desc) +{ + GByteArray *array; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + GError *error = NULL; + + array = crypto_load_and_verify_certificate (path, &format, &error); + ASSERT (array != NULL, desc, + "couldn't read certificate file '%s': %d %s", + path, error->code, error->message); + + ASSERT (format == NM_CRYPTO_FILE_FORMAT_X509, desc, + "%s: unexpected certificate format (expected %d, got %d)", + path, NM_CRYPTO_FILE_FORMAT_X509, format); + + g_byte_array_free (array, TRUE); +} + +static void +test_load_private_key (const char *path, + const char *password, + gboolean expect_fail, + const char *desc) +{ + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + GByteArray *array; + GError *error = NULL; + + array = crypto_get_private_key (path, password, &key_type, &format, &error); + if (expect_fail) { + ASSERT (array == NULL, desc, + "unexpected success reading private key file '%s' with " + "invalid password", + path); + + ASSERT (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN, desc, + "unexpected success determining private key file '%s' " + "format with invalid password (expected %d, got %d)", + path, NM_CRYPTO_FILE_FORMAT_UNKNOWN, format); + return; + } + + ASSERT (array != NULL, desc, + "couldn't read private key file '%s': %d %s", + path, error->code, error->message); + + ASSERT (format == NM_CRYPTO_FILE_FORMAT_RAW_KEY, desc, + "%s: unexpected private key file format (expected %d, got %d)", + path, NM_CRYPTO_FILE_FORMAT_RAW_KEY, format); + + ASSERT (key_type == NM_CRYPTO_KEY_TYPE_RSA, desc, + "%s: unexpected private key type (expected %d, got %d)", + path, NM_CRYPTO_KEY_TYPE_RSA, format); + + g_byte_array_free (array, TRUE); +} + +static void +test_load_pkcs12 (const char *path, + const char *password, + gboolean expect_fail, + const char *desc) +{ + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + GByteArray *array; + GError *error = NULL; + + array = crypto_get_private_key (path, password, &key_type, &format, &error); + if (expect_fail) { + ASSERT (array == NULL, desc, + "unexpected success reading PKCS#12 private key file " + "'%s' with invalid password", + path); + + /* PKCS#12 file format can be determined even if the password + * is wrong; check that. + */ + ASSERT (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN, desc, + "unexpected success determining PKCS#12 private key " + "'%s' file format with invalid password (expected %d, " + "got %d)", + path, NM_CRYPTO_FILE_FORMAT_UNKNOWN, format); + ASSERT (key_type == NM_CRYPTO_KEY_TYPE_UNKNOWN, desc, + "unexpected success determining PKCS#12 private key " + "'%s' type with invalid password (expected %d, got %d)", + path, NM_CRYPTO_KEY_TYPE_UNKNOWN, key_type); + return; + } + + ASSERT (array != NULL, desc, + "couldn't read PKCS#12 private key file '%s': %d %s", + path, error->code, error->message); + + ASSERT (format == NM_CRYPTO_FILE_FORMAT_PKCS12, desc, + "%s: unexpected PKCS#12 private key file format (expected %d, got %d)", + path, NM_CRYPTO_FILE_FORMAT_RAW_KEY, format); + + ASSERT (key_type == NM_CRYPTO_KEY_TYPE_ENCRYPTED, desc, + "%s: unexpected PKCS#12 private key type (expected %d, got %d)", + path, NM_CRYPTO_KEY_TYPE_ENCRYPTED, format); + + g_byte_array_free (array, TRUE); +} + +static void +test_is_pkcs12 (const char *path, gboolean expect_fail, const char *desc) +{ + gboolean is_pkcs12; + + is_pkcs12 = crypto_is_pkcs12_file (path, NULL); + if (expect_fail) { + ASSERT (is_pkcs12 == FALSE, desc, + "unexpected success reading non-PKCS#12 file '%s'", + path); + return; + } + + ASSERT (is_pkcs12 == TRUE, desc, "couldn't read PKCS#12 file '%s'", path); +} + +static void +test_encrypt_private_key (const char *path, + const char *password, + const char *desc) +{ + NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + GByteArray *array, *encrypted, *re_decrypted; + GError *error = NULL; + + array = crypto_get_private_key (path, password, &key_type, &format, &error); + + ASSERT (array != NULL, desc, + "couldn't read private key file '%s': %d %s", + path, error->code, error->message); + + ASSERT (format == NM_CRYPTO_FILE_FORMAT_RAW_KEY, desc, + "%s: unexpected private key file format (expected %d, got %d)", + path, NM_CRYPTO_FILE_FORMAT_RAW_KEY, format); + + ASSERT (key_type == NM_CRYPTO_KEY_TYPE_RSA, desc, + "%s: unexpected private key type (expected %d, got %d)", + path, NM_CRYPTO_KEY_TYPE_RSA, format); + + /* Now re-encrypt the private key */ + encrypted = nm_utils_rsa_key_encrypt (array, password, NULL, &error); + ASSERT (encrypted != NULL, desc, + "couldn't re-encrypt private key file '%s': %d %s", + path, error->code, error->message); + + /* Then re-decrypt the private key */ + key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN; + format = NM_CRYPTO_FILE_FORMAT_UNKNOWN; + re_decrypted = crypto_get_private_key_data (encrypted, password, &key_type, &format, &error); + + ASSERT (re_decrypted != NULL, desc, + "couldn't read private key file '%s': %d %s", + path, error->code, error->message); + + ASSERT (format == NM_CRYPTO_FILE_FORMAT_RAW_KEY, desc, + "%s: unexpected private key file format (expected %d, got %d)", + path, NM_CRYPTO_FILE_FORMAT_RAW_KEY, format); + + ASSERT (key_type == NM_CRYPTO_KEY_TYPE_RSA, desc, + "%s: unexpected private key type (expected %d, got %d)", + path, NM_CRYPTO_KEY_TYPE_RSA, format); + + /* Compare the original decrypted key with the re-decrypted key */ + ASSERT (array->len == re_decrypted->len, desc, + "%s: unexpected re-decrypted private key length (expected %d, got %d)", + path, array->len, re_decrypted->len); + + ASSERT (!memcmp (array->data, re_decrypted->data, array->len), desc, + "%s: unexpected private key data", + path); + + g_byte_array_free (re_decrypted, TRUE); + g_byte_array_free (encrypted, TRUE); + g_byte_array_free (array, TRUE); +} + +int main (int argc, char **argv) +{ + GError *error = NULL; + char *progname; + + ASSERT (argc > 2, "test-crypto", + "wrong number of arguments (expected at least an operation and an object)"); + + if (!crypto_init (&error)) + FAIL ("crypto-init", "failed to initialize crypto: %s", error->message); + + if (!strcmp (argv[1], "--cert")) + test_load_cert (argv[2], "cert"); + else if (!strcmp (argv[1], "--key")) { + ASSERT (argc == 4, "test-crypto", + "wrong number of arguments (--key <key file> <password>)"); + + test_load_private_key (argv[2], argv[3], FALSE, "private-key"); + test_load_private_key (argv[2], "blahblahblah", TRUE, "private-key-bad-password"); + test_encrypt_private_key (argv[2], argv[3], "private-key-rencrypt"); + test_is_pkcs12 (argv[2], TRUE, "is-pkcs12-not-pkcs12"); + } else if (!strcmp (argv[1], "--p12")) { + test_is_pkcs12 (argv[2], FALSE, "is-pkcs12"); + test_load_pkcs12 (argv[2], argv[3], FALSE, "pkcs12-private-key"); + test_load_pkcs12 (argv[2], "blahblahblah", TRUE, "pkcs12-private-key-bad-password"); + } else { + ASSERT (argc > 2, "test-crypto", "unknown test type (not --cert, --key, or --p12)"); + } + + crypto_deinit (); + + progname = g_path_get_basename (argv[0]); + fprintf (stdout, "%s: SUCCESS\n", progname); + g_free (progname); + return 0; +} + diff --git a/libnm-util/tests/test-general.c b/libnm-util/tests/test-general.c new file mode 100644 index 00000000..95304459 --- /dev/null +++ b/libnm-util/tests/test-general.c @@ -0,0 +1,246 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2008 - 2010 Red Hat, Inc. + * + */ + +#include <glib.h> +#include <dbus/dbus-glib.h> +#include <string.h> + +#include "nm-test-helpers.h" +#include <nm-utils.h> + +#include "nm-setting-connection.h" +#include "nm-setting-vpn.h" +#include "nm-setting-ip6-config.h" +#include "nm-dbus-glib-types.h" + +static void +vpn_check_func (const char *key, const char *value, gpointer user_data) +{ + const char *test = user_data; + + if (!strcmp (key, "foobar1")) { + ASSERT (strcmp (value, "blahblah1") == 0, + test, "unexpected vpn item '%s' / '%s'", key, value); + return; + } + + if (!strcmp (key, "foobar2")) { + ASSERT (strcmp (value, "blahblah2") == 0, + test, "unexpected vpn item '%s' / '%s'", key, value); + return; + } + + if (!strcmp (key, "foobar3")) { + ASSERT (strcmp (value, "blahblah3") == 0, + test, "unexpected vpn item '%s' / '%s'", key, value); + return; + } + + if (!strcmp (key, "foobar4")) { + ASSERT (strcmp (value, "blahblah4") == 0, + test, "unexpected vpn item '%s' / '%s'", key, value); + return; + } + + ASSERT (FALSE, test, "unexpected vpn item '%s'", key); +} + +static void +vpn_check_empty_func (const char *key, const char *value, gpointer user_data) +{ + const char *test = user_data; + + /* We don't expect any values */ + ASSERT (FALSE, test, "unexpected vpn item '%s'", key); +} + +static void +test_setting_vpn_items (void) +{ + NMSettingVPN *s_vpn; + + s_vpn = (NMSettingVPN *) nm_setting_vpn_new (); + ASSERT (s_vpn != NULL, + "vpn-items", + "error creating vpn setting"); + + nm_setting_vpn_add_data_item (s_vpn, "foobar1", "blahblah1"); + nm_setting_vpn_add_data_item (s_vpn, "foobar2", "blahblah2"); + nm_setting_vpn_add_data_item (s_vpn, "foobar3", "blahblah3"); + nm_setting_vpn_add_data_item (s_vpn, "foobar4", "blahblah4"); + + /* Ensure that added values are all present */ + nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_func, "vpn-data"); + nm_setting_vpn_remove_data_item (s_vpn, "foobar1"); + nm_setting_vpn_remove_data_item (s_vpn, "foobar2"); + nm_setting_vpn_remove_data_item (s_vpn, "foobar3"); + nm_setting_vpn_remove_data_item (s_vpn, "foobar4"); + + nm_setting_vpn_add_secret (s_vpn, "foobar1", "blahblah1"); + nm_setting_vpn_add_secret (s_vpn, "foobar2", "blahblah2"); + nm_setting_vpn_add_secret (s_vpn, "foobar3", "blahblah3"); + nm_setting_vpn_add_secret (s_vpn, "foobar4", "blahblah4"); + + /* Ensure that added values are all present */ + nm_setting_vpn_foreach_secret (s_vpn, vpn_check_func, "vpn-secrets"); + nm_setting_vpn_remove_secret (s_vpn, "foobar1"); + nm_setting_vpn_remove_secret (s_vpn, "foobar2"); + nm_setting_vpn_remove_secret (s_vpn, "foobar3"); + nm_setting_vpn_remove_secret (s_vpn, "foobar4"); + + /* Try to add some blank values and make sure they are rejected */ + nm_setting_vpn_add_data_item (s_vpn, NULL, NULL); + nm_setting_vpn_add_data_item (s_vpn, "", ""); + nm_setting_vpn_add_data_item (s_vpn, "foobar1", NULL); + nm_setting_vpn_add_data_item (s_vpn, "foobar1", ""); + nm_setting_vpn_add_data_item (s_vpn, NULL, "blahblah1"); + nm_setting_vpn_add_data_item (s_vpn, "", "blahblah1"); + + nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_empty_func, "vpn-data-empty"); + + /* Try to add some blank secrets and make sure they are rejected */ + nm_setting_vpn_add_secret (s_vpn, NULL, NULL); + nm_setting_vpn_add_secret (s_vpn, "", ""); + nm_setting_vpn_add_secret (s_vpn, "foobar1", NULL); + nm_setting_vpn_add_secret (s_vpn, "foobar1", ""); + nm_setting_vpn_add_secret (s_vpn, NULL, "blahblah1"); + nm_setting_vpn_add_secret (s_vpn, "", "blahblah1"); + + nm_setting_vpn_foreach_secret (s_vpn, vpn_check_empty_func, "vpn-secrets-empty"); + + g_object_unref (s_vpn); +} + +#define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID)) +#define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS)) + +/* Test that setting the IPv6 setting's 'addresses' property using the old + * IPv6 address format still works, i.e. that the GValue transformation function + * from old->new is working correctly. + */ +static void +test_setting_ip6_config_old_address_array (void) +{ + NMSettingIP6Config *s_ip6; + GPtrArray *addresses, *read_addresses; + GValueArray *array, *read_array; + GValue element = {0, }, written_value = {0, }, read_value = {0, }; + GByteArray *ba; + const guint8 addr[16] = { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, + 0x11, 0x22, 0x33, 0x44, 0x66, 0x77, 0x88, 0x99 }; + const guint8 gw[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + guint32 prefix = 56; + GValue *read_addr, *read_prefix, *read_gw; + + s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new (); + ASSERT (s_ip6 != NULL, + "ip6-old-addr", "error creating IP6 setting"); + + g_value_init (&written_value, OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS); + + addresses = g_ptr_array_new (); + array = g_value_array_new (3); + + /* IP address */ + g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); + ba = g_byte_array_new (); + g_byte_array_append (ba, &addr[0], sizeof (addr)); + g_value_take_boxed (&element, ba); + g_value_array_append (array, &element); + g_value_unset (&element); + + /* Prefix */ + g_value_init (&element, G_TYPE_UINT); + g_value_set_uint (&element, prefix); + g_value_array_append (array, &element); + g_value_unset (&element); + + g_ptr_array_add (addresses, array); + g_value_set_boxed (&written_value, addresses); + + /* Set the address array on the object */ + g_object_set_property (G_OBJECT (s_ip6), NM_SETTING_IP6_CONFIG_ADDRESSES, &written_value); + + /* Get it back so we can compare it */ + g_value_init (&read_value, DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS); + g_object_get_property (G_OBJECT (s_ip6), NM_SETTING_IP6_CONFIG_ADDRESSES, &read_value); + + ASSERT (G_VALUE_HOLDS (&read_value, DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS), + "ip6-old-addr", "wrong addresses property value type '%s'", + G_VALUE_TYPE_NAME (&read_value)); + + read_addresses = (GPtrArray *) g_value_get_boxed (&read_value); + ASSERT (read_addresses != NULL, + "ip6-old-addr", "missing addresses on readback"); + ASSERT (read_addresses->len == 1, + "ip6-old-addr", "expected one address on readback"); + + read_array = (GValueArray *) g_ptr_array_index (read_addresses, 0); + + read_addr = g_value_array_get_nth (read_array, 0); + ba = g_value_get_boxed (read_addr); + ASSERT (ba->len == sizeof (addr), + "ip6-old-addr", "unexpected address item length %d", ba->len); + ASSERT (memcmp (ba->data, &addr[0], sizeof (addr)) == 0, + "ip6-old-addr", "unexpected failure comparing addresses"); + + read_prefix = g_value_array_get_nth (read_array, 1); + ASSERT (g_value_get_uint (read_prefix) == prefix, + "ip6-old-addr", "unexpected failure comparing prefix"); + + /* Ensure the gateway is all zeros, which is how the 2-item to 3-item + * conversion happens. + */ + read_gw = g_value_array_get_nth (read_array, 2); + ba = g_value_get_boxed (read_gw); + ASSERT (ba->len == sizeof (gw), + "ip6-old-addr", "unexpected gateway item length %d", ba->len); + ASSERT (memcmp (ba->data, &gw[0], sizeof (gw)) == 0, + "ip6-old-addr", "unexpected failure comparing gateways"); + + g_value_unset (&written_value); + g_value_unset (&read_value); + g_object_unref (s_ip6); +} + +int main (int argc, char **argv) +{ + GError *error = NULL; + DBusGConnection *bus; + char *base; + + g_type_init (); + bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + + if (!nm_utils_init (&error)) + FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + + /* The tests */ + test_setting_vpn_items (); + test_setting_ip6_config_old_address_array (); + + base = g_path_get_basename (argv[0]); + fprintf (stdout, "%s: SUCCESS\n", base); + g_free (base); + return 0; +} + diff --git a/libnm-util/tests/test-need-secrets.c b/libnm-util/tests/test-need-secrets.c new file mode 100644 index 00000000..517e2e01 --- /dev/null +++ b/libnm-util/tests/test-need-secrets.c @@ -0,0 +1,566 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2008 - 2009 Red Hat, Inc. + * + */ + +#include <glib.h> +#include <dbus/dbus-glib.h> +#include <string.h> + +#include "nm-test-helpers.h" +#include <nm-utils.h> + +#include "nm-setting-connection.h" +#include "nm-setting-wired.h" +#include "nm-setting-8021x.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-wireless-security.h" +#include "nm-setting-cdma.h" +#include "nm-setting-gsm.h" +#include "nm-setting-ppp.h" +#include "nm-setting-pppoe.h" +#include "nm-setting-vpn.h" + + +#define TEST_NEED_SECRETS_EAP_TLS_CA_CERT TEST_CERT_DIR "/test_ca_cert.pem" +#define TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT TEST_CERT_DIR "/test_key_and_cert.pem" +#define TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY TEST_CERT_DIR "/test_key_and_cert.pem" + +static gboolean +find_hints_item (GPtrArray *hints, const char *item) +{ + int i; + + for (i = 0; i < hints->len; i++) { + if (!strcmp (item, (const char *) g_ptr_array_index (hints, i))) + return TRUE; + } + return FALSE; +} + +static NMConnection * +make_tls_connection (const char *detail, NMSetting8021xCKScheme scheme) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSetting8021x *s_8021x; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + detail, "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Need TLS Secrets", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + ASSERT (s_wired != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_WIRED_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + /* Wireless security setting */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + ASSERT (s_8021x != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_802_1X_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); + + g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); + + nm_setting_802_1x_add_eap_method (s_8021x, "tls"); + + success = nm_setting_802_1x_set_ca_cert (s_8021x, + TEST_NEED_SECRETS_EAP_TLS_CA_CERT, + scheme, + NULL, + &error); + ASSERT (success == TRUE, + detail, "failed to set CA certificate '%s': %s", + TEST_NEED_SECRETS_EAP_TLS_CA_CERT, error->message); + + success = nm_setting_802_1x_set_client_cert (s_8021x, + TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT, + scheme, + NULL, + &error); + ASSERT (success == TRUE, + detail, "failed to set client certificate '%s': %s", + TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT, error->message); + + success = nm_setting_802_1x_set_private_key (s_8021x, + TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY, + "test", + scheme, + NULL, + &error); + ASSERT (success == TRUE, + detail, "failed to set private key '%s': %s", + TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY, error->message); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + detail, "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + return connection; +} + +static void +test_need_tls_secrets_path (void) +{ + NMConnection *connection; + const char *setting_name; + GPtrArray *hints = NULL; + NMSetting8021x *s_8021x; + + connection = make_tls_connection ("need-tls-secrets-path-key", NM_SETTING_802_1X_CK_SCHEME_PATH); + ASSERT (connection != NULL, + "need-tls-secrets-path-key", + "error creating test connection"); + + /* Ensure we don't need any secrets since we just set up the connection */ + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name == NULL, + "need-tls-secrets-path-key", + "secrets are unexpectedly required"); + ASSERT (hints == NULL, + "need-tls-secrets-path-key", + "hints should be NULL since no secrets were required"); + + /* Connection is good; clear secrets and ensure private key is then required */ + nm_connection_clear_secrets (connection); + + hints = NULL; + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name != NULL, + "need-tls-secrets-path-key", + "unexpected secrets success"); + ASSERT (strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME) == 0, + "need-tls-secrets-path-key", + "unexpected setting secrets required"); + + ASSERT (hints != NULL, + "need-tls-secrets-path-key", + "expected returned secrets hints"); + ASSERT (find_hints_item (hints, NM_SETTING_802_1X_PRIVATE_KEY), + "need-tls-secrets-path-key", + "expected to require private key, but it wasn't"); + + g_object_unref (connection); + + /*** Just clear the private key this time ***/ + + connection = make_tls_connection ("need-tls-secrets-path-key-password", NM_SETTING_802_1X_CK_SCHEME_PATH); + ASSERT (connection != NULL, + "need-tls-secrets-path-key-password", + "error creating test connection"); + + s_8021x = (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X); + ASSERT (s_8021x != NULL, + "need-tls-secrets-path-key-password", + "error getting test 802.1x setting"); + + g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, NULL, NULL); + + hints = NULL; + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name != NULL, + "need-tls-secrets-path-key-password", + "unexpected secrets success"); + ASSERT (strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME) == 0, + "need-tls-secrets-path-key-password", + "unexpected setting secrets required"); + + ASSERT (hints != NULL, + "need-tls-secrets-path-key-password", + "expected returned secrets hints"); + ASSERT (find_hints_item (hints, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD), + "need-tls-secrets-path-key-password", + "expected to require private key password, but it wasn't"); + + g_object_unref (connection); +} + +static void +test_need_tls_secrets_blob (void) +{ + NMConnection *connection; + const char *setting_name; + GPtrArray *hints = NULL; + NMSetting8021x *s_8021x; + + connection = make_tls_connection ("need-tls-secrets-blob-key", NM_SETTING_802_1X_CK_SCHEME_BLOB); + ASSERT (connection != NULL, + "need-tls-secrets-blob-key", + "error creating test connection"); + + /* Ensure we don't need any secrets since we just set up the connection */ + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name == NULL, + "need-tls-secrets-blob-key", + "secrets are unexpectedly required"); + ASSERT (hints == NULL, + "need-tls-secrets-blob-key", + "hints should be NULL since no secrets were required"); + + /* Connection is good; clear secrets and ensure private key is then required */ + nm_connection_clear_secrets (connection); + + hints = NULL; + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name != NULL, + "need-tls-secrets-blob-key", + "unexpected secrets success"); + ASSERT (strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME) == 0, + "need-tls-secrets-blob-key", + "unexpected setting secrets required"); + + ASSERT (hints != NULL, + "need-tls-secrets-blob-key", + "expected returned secrets hints"); + ASSERT (find_hints_item (hints, NM_SETTING_802_1X_PRIVATE_KEY), + "need-tls-secrets-blob-key", + "expected to require private key, but it wasn't"); + + g_object_unref (connection); + + /*** Just clear the private key this time ***/ + + connection = make_tls_connection ("need-tls-secrets-blob-key-password", NM_SETTING_802_1X_CK_SCHEME_BLOB); + ASSERT (connection != NULL, + "need-tls-secrets-blob-key-password", + "error creating test connection"); + + s_8021x = (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X); + ASSERT (s_8021x != NULL, + "need-tls-secrets-blob-key-password", + "error getting test 802.1x setting"); + + g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, NULL, NULL); + + /* Blobs are already decrypted and don't need a password */ + hints = NULL; + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name == NULL, + "need-tls-secrets-blob-key-password", + "unexpected secrets failure"); + ASSERT (hints == NULL, + "need-tls-secrets-blob-key-password", + "hints should be NULL since no secrets were required"); + + g_object_unref (connection); +} + +static NMConnection * +make_tls_phase2_connection (const char *detail, NMSetting8021xCKScheme scheme) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSetting8021x *s_8021x; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + char *uuid; + gboolean success; + GError *error = NULL; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + detail, "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Need TLS Secrets", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + ASSERT (s_wired != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_WIRED_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + /* Wireless security setting */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + ASSERT (s_8021x != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_802_1X_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); + + g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "blahblah", NULL); + g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); + + nm_setting_802_1x_add_eap_method (s_8021x, "ttls"); + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "tls", NULL); + + success = nm_setting_802_1x_set_phase2_ca_cert (s_8021x, + TEST_NEED_SECRETS_EAP_TLS_CA_CERT, + scheme, + NULL, + &error); + ASSERT (success == TRUE, + detail, "failed to set phase2 CA certificate '%s': %s", + TEST_NEED_SECRETS_EAP_TLS_CA_CERT, error->message); + + success = nm_setting_802_1x_set_phase2_client_cert (s_8021x, + TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT, + scheme, + NULL, + &error); + ASSERT (success == TRUE, + detail, "failed to set phase2 client certificate '%s': %s", + TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT, error->message); + + success = nm_setting_802_1x_set_phase2_private_key (s_8021x, + TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY, + "test", + scheme, + NULL, + &error); + ASSERT (success == TRUE, + detail, "failed to set phase2 private key '%s': %s", + TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY, error->message); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + detail, "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + detail, "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + return connection; +} + +static void +test_need_tls_phase2_secrets_path (void) +{ + NMConnection *connection; + const char *setting_name; + GPtrArray *hints = NULL; + NMSetting8021x *s_8021x; + + connection = make_tls_phase2_connection ("need-tls-phase2-secrets-path-key", + NM_SETTING_802_1X_CK_SCHEME_PATH); + ASSERT (connection != NULL, + "need-tls-phase2-secrets-path-key", + "error creating test connection"); + + /* Ensure we don't need any secrets since we just set up the connection */ + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name == NULL, + "need-tls-phase2-secrets-path-key", + "secrets are unexpectedly required"); + ASSERT (hints == NULL, + "need-tls-phase2-secrets-path-key", + "hints should be NULL since no secrets were required"); + + /* Connection is good; clear secrets and ensure private key is then required */ + nm_connection_clear_secrets (connection); + + hints = NULL; + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name != NULL, + "need-tls-phase2-secrets-path-key", + "unexpected secrets success"); + ASSERT (strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME) == 0, + "need-tls-phase2-secrets-path-key", + "unexpected setting secrets required"); + + ASSERT (hints != NULL, + "need-tls-phase2-secrets-path-key", + "expected returned secrets hints"); + ASSERT (find_hints_item (hints, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY), + "need-tls-phase2-secrets-path-key", + "expected to require private key, but it wasn't"); + + g_object_unref (connection); + + /*** Just clear the private key this time ***/ + + connection = make_tls_phase2_connection ("need-tls-phase2-secrets-path-key-password", + NM_SETTING_802_1X_CK_SCHEME_PATH); + ASSERT (connection != NULL, + "need-tls-phase2-secrets-path-key-password", + "error creating test connection"); + + s_8021x = (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X); + ASSERT (s_8021x != NULL, + "need-tls-phase2-secrets-path-key-password", + "error getting test 802.1x setting"); + + g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, NULL, NULL); + + hints = NULL; + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name != NULL, + "need-tls-phase2-secrets-path-key-password", + "unexpected secrets success"); + ASSERT (strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME) == 0, + "need-tls-phase2-secrets-path-key-password", + "unexpected setting secrets required"); + + ASSERT (hints != NULL, + "need-tls-phase2-secrets-path-key-password", + "expected returned secrets hints"); + ASSERT (find_hints_item (hints, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD), + "need-tls-phase2-secrets-path-key-password", + "expected to require private key password, but it wasn't"); + + g_object_unref (connection); +} + +static void +test_need_tls_phase2_secrets_blob (void) +{ + NMConnection *connection; + const char *setting_name; + GPtrArray *hints = NULL; + NMSetting8021x *s_8021x; + + connection = make_tls_phase2_connection ("need-tls-phase2-secrets-blob-key", + NM_SETTING_802_1X_CK_SCHEME_BLOB); + ASSERT (connection != NULL, + "need-tls-phase2-secrets-blob-key", + "error creating test connection"); + + /* Ensure we don't need any secrets since we just set up the connection */ + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name == NULL, + "need-tls-phase2-secrets-blob-key", + "secrets are unexpectedly required"); + ASSERT (hints == NULL, + "need-tls-phase2-secrets-blob-key", + "hints should be NULL since no secrets were required"); + + /* Connection is good; clear secrets and ensure private key is then required */ + nm_connection_clear_secrets (connection); + + hints = NULL; + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name != NULL, + "need-tls-phase2-secrets-blob-key", + "unexpected secrets success"); + ASSERT (strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME) == 0, + "need-tls-phase2-secrets-blob-key", + "unexpected setting secrets required"); + + ASSERT (hints != NULL, + "need-tls-phase2-secrets-blob-key", + "expected returned secrets hints"); + ASSERT (find_hints_item (hints, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY), + "need-tls-phase2-secrets-blob-key", + "expected to require private key, but it wasn't"); + + g_object_unref (connection); + + /*** Just clear the private key this time ***/ + + connection = make_tls_phase2_connection ("need-tls-phase2-secrets-blob-key-password", + NM_SETTING_802_1X_CK_SCHEME_BLOB); + ASSERT (connection != NULL, + "need-tls-phase2-secrets-blob-key-password", + "error creating test connection"); + + s_8021x = (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X); + ASSERT (s_8021x != NULL, + "need-tls-phase2-secrets-blob-key-password", + "error getting test 802.1x setting"); + + g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, NULL, NULL); + + /* Blobs are already decrypted and don't need a password */ + hints = NULL; + setting_name = nm_connection_need_secrets (connection, &hints); + ASSERT (setting_name == NULL, + "need-tls-phase2-secrets-blob-key-password", + "unexpected secrets failure"); + ASSERT (hints == NULL, + "need-tls-phase2-secrets-blob-key-password", + "hints should be NULL since no secrets were required"); + + g_object_unref (connection); +} + +int main (int argc, char **argv) +{ + GError *error = NULL; + DBusGConnection *bus; + char *base; + + g_type_init (); + bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + + if (!nm_utils_init (&error)) + FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + + /* The tests */ + test_need_tls_secrets_path (); + test_need_tls_secrets_blob (); + test_need_tls_phase2_secrets_path (); + test_need_tls_phase2_secrets_blob (); + + base = g_path_get_basename (argv[0]); + fprintf (stdout, "%s: SUCCESS\n", base); + g_free (base); + return 0; +} + diff --git a/libnm-util/tests/test-setting-8021x.c b/libnm-util/tests/test-setting-8021x.c new file mode 100644 index 00000000..6202a142 --- /dev/null +++ b/libnm-util/tests/test-setting-8021x.c @@ -0,0 +1,163 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2008 - 2009 Red Hat, Inc. + * + */ + +#include <glib.h> +#include <dbus/dbus-glib.h> +#include <string.h> + +#include "nm-test-helpers.h" +#include <nm-utils.h> + +#include "nm-setting-connection.h" +#include "nm-setting-8021x.h" + +static void +compare_decrypted (const char *test, + const char *decrypted_path, + const GByteArray *key) +{ + char *contents = NULL; + gsize len = 0; + GError *error = NULL; + gboolean success; + + success = g_file_get_contents (decrypted_path, &contents, &len, &error); + ASSERT (success == TRUE, + test, "failed to read decrypted key file: %s", error->message); + + ASSERT (len > 0, test, "decrypted key file invalid (size 0)"); + + ASSERT (len == key->len, + test, "decrypted key file (%d) and decrypted key data (%d) lengths don't match", + len, key->len); + + ASSERT (memcmp (contents, key->data, len) == 0, + test, "decrypted key file and decrypted key data don't match"); + + g_free (contents); +} + +static void +test_private_key_import (const char *path, + const char *password, + const char *decrypted_path, + NMSetting8021xCKScheme scheme) +{ + NMSetting8021x *s_8021x; + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + GError *error = NULL; + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + ASSERT (s_8021x != NULL, "private-key-import", "setting was NULL"); + + success = nm_setting_802_1x_set_private_key (s_8021x, + path, + password, + scheme, + &format, + &error); + ASSERT (success == TRUE, + "private-key-import", "error reading private key: %s", error->message); + + if ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB + && format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) { + const GByteArray *key; + + ASSERT (decrypted_path != NULL, "private-key-import", "missing decrypted key file"); + + key = nm_setting_802_1x_get_private_key_blob (s_8021x); + ASSERT (key != NULL, "private-key-import", "missing private key blob"); + compare_decrypted ("private-key-import", decrypted_path, key); + } + + g_object_unref (s_8021x); +} + +static void +test_phase2_private_key_import (const char *path, + const char *password, + const char *decrypted_path, + NMSetting8021xCKScheme scheme) +{ + NMSetting8021x *s_8021x; + gboolean success; + NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; + GError *error = NULL; + + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); + ASSERT (s_8021x != NULL, "phase2-private-key-import", "setting was NULL"); + + success = nm_setting_802_1x_set_phase2_private_key (s_8021x, + path, + password, + scheme, + &format, + &error); + ASSERT (success == TRUE, + "phase2-private-key-import", "error reading private key: %s", error->message); + + if ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB + && format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) { + const GByteArray *key; + + ASSERT (decrypted_path != NULL, "phase2-private-key-import", "missing decrypted key file"); + + key = nm_setting_802_1x_get_phase2_private_key_blob (s_8021x); + ASSERT (key != NULL, "phase2-private-key-import", "missing private key blob"); + compare_decrypted ("phase2-private-key-import", decrypted_path, key); + } + + g_object_unref (s_8021x); +} + +int main (int argc, char **argv) +{ + GError *error = NULL; + DBusGConnection *bus; + char *base; + const char *decrypted = NULL; + + if (argc < 3) + FAIL ("init", "need at least two arguments: <path> <password> [decrypted private key]"); + + if (argc == 4) + decrypted = argv[3]; + + g_type_init (); + bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + + if (!nm_utils_init (&error)) + FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + + /* The tests */ + test_private_key_import (argv[1], argv[2], NULL, NM_SETTING_802_1X_CK_SCHEME_PATH); + test_phase2_private_key_import (argv[1], argv[2], NULL, NM_SETTING_802_1X_CK_SCHEME_PATH); + + test_private_key_import (argv[1], argv[2], decrypted, NM_SETTING_802_1X_CK_SCHEME_BLOB); + test_phase2_private_key_import (argv[1], argv[2], decrypted, NM_SETTING_802_1X_CK_SCHEME_BLOB); + + base = g_path_get_basename (argv[0]); + fprintf (stdout, "%s: SUCCESS\n", base); + g_free (base); + return 0; +} + diff --git a/libnm-util/tests/test-settings-defaults.c b/libnm-util/tests/test-settings-defaults.c new file mode 100644 index 00000000..9f38a145 --- /dev/null +++ b/libnm-util/tests/test-settings-defaults.c @@ -0,0 +1,135 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2008 Red Hat, Inc. + * + */ + +#include <glib.h> +#include <dbus/dbus-glib.h> +#include <string.h> + +#include "nm-test-helpers.h" +#include <nm-utils.h> + +#include "nm-setting-8021x.h" +#include "nm-setting-cdma.h" +#include "nm-setting-connection.h" +#include "nm-setting-gsm.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-setting-ppp.h" +#include "nm-setting-pppoe.h" +#include "nm-setting-serial.h" +#include "nm-setting-vpn.h" +#include "nm-setting-wired.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wireless-security.h" + + +static void +test_defaults (GType type, const char *name) +{ + GParamSpec **property_specs; + guint n_property_specs; + GObject *setting; + int i; + + setting = g_object_new (type, NULL); + + property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); + ASSERT (property_specs != NULL, + name, "couldn't find property specs for object of type '%s'", + g_type_name (G_OBJECT_TYPE (setting))); + + for (i = 0; i < n_property_specs; i++) { + GParamSpec *prop_spec = property_specs[i]; + GValue value = { 0, }; + GValue defvalue = { 0, }; + char *actual, *expected; + gboolean ok = FALSE; + + /* Ignore non-fundamental types since they won't really have + * defaults. + */ + if (!G_TYPE_IS_FUNDAMENTAL (prop_spec->value_type)) + continue; + + g_value_init (&value, prop_spec->value_type); + g_object_get_property (G_OBJECT (setting), prop_spec->name, &value); + + g_value_init (&defvalue, prop_spec->value_type); + g_param_value_set_default (prop_spec, &defvalue); + + actual = g_strdup_value_contents (&value); + expected = g_strdup_value_contents (&defvalue); + + if (!strcmp (prop_spec->name, NM_SETTING_NAME)) { + /* 'name' is always the setting name, not the default value */ + ok = !strcmp (nm_setting_get_name (NM_SETTING (setting)), name); + g_free (expected); + expected = g_strdup (name); + } else + ok = g_param_value_defaults (prop_spec, &value); + + ASSERT (ok, + name, "property '%s' value '%s' not the expected default value '%s'", + prop_spec->name, actual, expected); + + g_free (actual); + g_free (expected); + g_value_unset (&value); + g_value_unset (&defvalue); + } + + g_free (property_specs); + g_object_unref (setting); +} + +int main (int argc, char **argv) +{ + GError *error = NULL; + DBusGConnection *bus; + char *base; + + g_type_init (); + bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + + if (!nm_utils_init (&error)) + FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + + /* The tests */ + test_defaults (NM_TYPE_SETTING_CONNECTION, NM_SETTING_CONNECTION_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_802_1X, NM_SETTING_802_1X_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_CDMA, NM_SETTING_CDMA_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_GSM, NM_SETTING_GSM_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_IP4_CONFIG, NM_SETTING_IP4_CONFIG_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_IP6_CONFIG, NM_SETTING_IP6_CONFIG_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_PPP, NM_SETTING_PPP_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_PPPOE, NM_SETTING_PPPOE_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_SERIAL, NM_SETTING_SERIAL_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_VPN, NM_SETTING_VPN_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_WIRED, NM_SETTING_WIRED_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_WIRELESS, NM_SETTING_WIRELESS_SETTING_NAME); + test_defaults (NM_TYPE_SETTING_WIRELESS_SECURITY, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + + base = g_path_get_basename (argv[0]); + fprintf (stdout, "%s: SUCCESS\n", base); + g_free (base); + return 0; +} + |