Table of Contents

Cover

Title Page

Copyright

About the Author

Credits

Acknowledgments

Introduction

Who Should Read This Book

What Are We Trying to Secure, and from What?

About the Examples

Conventions Used in This Book

Source Code

Errata

p2p.wrox.com

Chapter 1: Secure by Design

About Cocoa Security

Profiling Your Application’s Security Risks

Defining the Security Environment

Defining Threats

Defining and Mitigating Vulnerabilities

Summary

Chapter 2: Managing Multiple Users

Caveat for iPhone Developers

Why We Have Multiple Users

User Groups

Understanding Directory Services

Accessing User Preferences and Managed Preferences

Summary

Chapter 3: Using the Filesystem Securely

UNIX Permissions

Filesystem Flags

Access Control Lists

FileVault and Other Encryption Options

Network Filesystems

Layout and Security of a Typical Mac OS X Filesystem

Aliases and Bookmarks

Quarantining Downloaded Files

Securely Deleting Files

Disk Arbitration

Summary

Chapter 4: Handling Multiple Processes

Privilege Separation

Designing Multiple-Process Systems

Managing Process Lifecycles with Launchd

How to Use Setuid and Setgid

Communication between Processes

Playing in the Sandbox

Guaranteeing Code’s Origin

Summary

Chapter 5: Storing Confidential Data in the Keychain

What Is the Keychain?

Why Should I Use the Keychain?

How to Take Advantage of the Keychain

Keychain on the iPhone

Summary

Chapter 6: Performing Privileged Tasks

How to Acquire Rights

Factored Applications with Authorization Services

The Authorization Database

Why Not to Launch Privileged Tasks with Authorization Services

The Padlock

Authorization Plug-Ins

Summary

Chapter 7: Auditing Important Operations

Examples of Auditing

Using Apple System Logger

Basic Security Module

Summary

Chapter 8: Securing Network Connections

Remote Authentication

Privilege Boundaries in Networked Applications

Does ‘Bonjour’ Mean It’s Adieu to Network Security?

Working with the Firewall

Network Configuration with SystemConfiguration

Taking Advantage of SSL

Summary

Chapter 9: Writing Secure Application Code

Secure Objective-C Coding

Secure C Coding

Code Reviews and Other Bug-Finding Techniques

Summary

Chapter 10: Deploying Software Securely

Writing Security Documentation

Identify Yourself with Code Signing

Giving Your Code to Your Users

Rolling Your Own Installer

Deploying Privileged Helpers without Installers

Responding to Security Problems

Summary

Chapter 11: Kernel Extensions

The Kernel Environment

Filesystem Access Authorization with Kauth

Summary

Chapter 12: Conclusion and Further Reading

Further Reading

Index

Professional Cocoa® Application Security

Published by
Wiley Publishing, Inc.
10475 Crosspoint Boulevard
Indianapolis, IN 46256
www.wiley.com

Copyright © 2010 by Wiley Publishing, Inc., Indianapolis, Indiana

ISBN: 978-0-470-52595-1

ISBN: 978-0-470-88704-2 (ebk)

ISBN: 978-0-470-88706-6 (ebk)

Manufactured in the United States of America

10 9 8 7 6 5 4 3 2 1

No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise, except as permitted under Sections 107 or 108 of the 1976 United States Copyright Act, without either the prior written permission of the Publisher, or authorization through payment of the appropriate per-copy fee to the Copyright Clearance Center, 222 Rosewood Drive, Danvers, MA 01923, (978) 750-8400, fax (978) 646-8600. Requests to the Publisher for permission should be addressed to the Permissions Department, John Wiley & Sons, Inc., 111 River Street, Hoboken, NJ 07030, (201) 748-6011, fax (201) 748-6008, or online at http://www.wiley.com/go/permissions.

Limit of Liability/Disclaimer of Warranty: The publisher and the author make no representations or warranties with respect to the accuracy or completeness of the contents of this work and specifically disclaim all warranties, including without limitation warranties of fitness for a particular purpose. No warranty may be created or extended by sales or promotional materials. The advice and strategies contained herein may not be suitable for every situation. This work is sold with the understanding that the publisher is not engaged in rendering legal, accounting, or other professional services. If professional assistance is required, the services of a competent professional person should be sought. Neither the publisher nor the author shall be liable for damages arising herefrom. The fact that an organization or Web site is referred to in this work as a citation and/or a potential source of further information does not mean that the author or the publisher endorses the information the organization or Web site may provide or recommendations it may make. Further, readers should be aware that Internet Web sites listed in this work may have changed or disappeared between when this work was written and when it is read.

For general information on our other products and services please contact our Customer Care Department within the United States at (877) 762-2974, outside the United States at (317) 572-3993 or fax (317) 572-4002.

Wiley also publishes its books in a variety of electronic formats. Some content that appears in print may not be available in electronic books.

Library of Congress Control Number: 2010926599

Trademarks: Wiley, the Wiley logo, Wrox, the Wrox logo, Wrox Programmer to Programmer, and related trade dress are trademarks or registered trademarks of John Wiley & Sons, Inc. and/or its affiliates, in the United States and other countries, and may not be used without written permission. Cocoa is a registered trademark of Apple, Inc. All other trademarks are the property of their respective owners. Wiley Publishing, Inc. is not associated with any product or vendor mentioned in this book.

About the Author

Graham J. Lee is an independent Mac, iPhone and iPad contract developer. He lives in Oxford, England with his girl friend and an ever-growing collection of vegetables. Graham maintains a security column for the Mac Developer Network, and discusses Cocoa security issues on the network’s podcast, “The MDN Show.”

He has spoken to conferences and university courses on security matters. He is also studying for a postgraduate qualification in software security from Oxford University. In his spare time, Graham tries to find out where all his spare time went.

About the Technical Editor

James Lyne is a security and technology strategist who grew up with technology (his first computer was a Mac!). Working with some of the world’s largest and most paranoid enterprises to form security strategy, James has seen it all go wrong in detail. Coming from a background of mathematics and cryptography, he has a range of experience from detailed implementation to broad strategy. He holds a collection of qualifications and industry awards from a variety of institutes and also contributes heavily to education, presenting at open public forums on security challenges for the coming years.

Credits

Acquisitions Editor

Scott Meyers

Project Editor

William Bridges

Technical Editor

James Lyne

Production Editor

Daniel Scribner

Copy Editor

Sadie Kleinman

Editorial Director

Robyn B. Siesky

Editorial Manager

Mary Beth Wakefield

Marketing Manager

David Mayhew

Production Manager

Tim Tate

Vice President and Executive Group Publisher

Richard Swadley

Vice President and Executive Publisher

Barry Pruett

Associate Publisher

Jim Minatel

Project Coordinator, Cover

Lynsey Stanford

Compositor

Craig Woods, Happenstance Type-O-Rama

Proofreader

Nancy Bell

Indexer

Robert Swanson

Cover Design

Michael E. Trent

Cover Image

© Duncan Walker/istockphoto

Acknowledgments

The most important contribution to this book, I must acknowledge, is from the Mac developer community. Thanks, everyone, for showing me that application security does need a champion, and for all your suggestions of topics to cover here and in the Mac Developer Network. Special mention and gratitude must go to Steve “Scotty” Scott for accepting that in lieu of a better option, I could be that champion.

Scott originally suggested that I write a book and James, Sadie and Bill all did a great job of beating my drafts into a publishable state: I’m very grateful to all of them. Of course, I assume full responsibility for any errors that snuck through. Finally, a developer is only as good as the caffeine that fuels him, so particular thanks are due to Freya for her fine supply of coffee and moral support.

Introduction

The world in which we use today’s iMacs and MacBooks has little in common with the world of the first Macintosh computer Steve Jobs unveiled in 1984. The idea that everybody would be using a computer at home and at work — and indeed on the road — with permanent connections to the rest of the world via the Internet would have been thought out of the question back then. Forget completely the idea that people could carry full-featured computer/telephone/music player/camera devices in their jeans pockets. Or that you would be able to use your laptop or even your mobile phone to organize your finances with your bank, buy the latest movies, and get on with your work while away from the office. Taken to the extreme now, such technology is actually starting to provide dynamic connections between the digital and physical world — for example allowing you to photograph a physical object and associate it with online content such as a shop store or reviews. This is undoubtedly convenient, but it also brings new risks that were unheard of when the computers, their operating systems, and many of their applications were designed.

The organization Fight Identity Theft (http://www.fightidentitytheft.com) claims that identity theft cost 8.4 million Americans a total of $49.3 billion in 2008. The impact on any individual victim can be ruinous. As a result, this and other “cybercrimes” receive a lot of coverage in the media. It’s reported frequently that a company or government department has leaked thousands of personal records; the hit the organization’s reputation takes can easily be worse than the direct liability for the loss, such as government fines. Therefore, the total cost of the crime is unknown — businesses prefer not to disclose details unless obliged to, so we don’t find exact figures for corporate identity theft. However, it is evident just from visible cases that the impact of such misconduct can be vast, and since the commercial world is increasingly underpinned by data as a key asset, security is high on the agenda of business risks.

Traditionally viruses, worms, and Trojan horses (collectively, “malware”) have been seen by Mac users as Windows-only phenomena; they’ve quickly forgotten the Autostart problems of the 1990s and dismissed modern OS X malware as proof-of-concept or otherwise something that “real” Mac users need not worry about. Presumably the Mac malware infects only those machines owned by fake Mac owners, whoever they are. The reality is, of course, somewhat different from this simplistic picture. It’s true that much less malicious software is known to target the Mac. But the way this software is sent to the victim’s computer, the way the user is tricked into installing it, and the actions it takes once installed are the same on both platforms. Many attacks now involve a web server’s detecting whether the user has a Mac or PC, and sending the appropriate malware in each case, as described in http://blog.trendmicro.com/more-mac-malware-in-the-wild/.

A successful attack does not need to start with the user’s downloading a malicious application such as a Trojan horse. A whole class of “data-driven” attacks relies on being able to subvert a legitimate application to the attacker’s ends by feeding it data that it cannot handle properly. A well-publicized example is one of the early “jail-breaking” tools for the iPhone, which used an error in the way Mobile Safari loaded TIFF images to cause Mobile Safari to run the jail-breaking code.

Then there are the more personal security compromises, which don’t generate as many headlines or column inches as the big cybercrimes but nonetheless cause the victims to question their choice of applications and vendors. Finding that someone else has posted to the victim’s Twitter account, or that his or her partner has been reading private e-mails or online banking statements, are examples of this form of attack.

Despite all these problems, there is no need to paint a picture of doom. If mitigating risk in software were a futile effort, there would be no need for the rest of this book. In Mac OS X and the iPhone OS, Apple has made a number of significant enhancements to the traditional UNIX platform design in order to improve its relevance in the 21st century. You, as a software developer working on those platforms, can easily spend some small amount of time on security considerations when designing your applications, which results in a big return for your users who receive a more secure product. You can identify the risks that will be present when the application is deployed to your users, and work to reduce the impact of those risks. The risks you deal with will be those that are relevant to the modern environment, with its modern threats; you don’t need to (and indeed no longer can) rely on application conventions from the 1980s. You can develop your applications with an eye on security, so that they cannot be hijacked as they help their users communicate with people across the world. You can also communicate with your users in an open and honest manner, so that they understand the risks you’re helping them to avoid, those risks you aren’t, and the users’ part in reducing all of them.

In Mac OS X and the iPhone OS, Apple has provided a number of APIs and security features that you can take advantage of in your applications to improve the security of those applications. Integrating with these features is as much a part of the overall user experience as is integration with “headline” features such as Spotlight or Automator. By providing a security experience consistent with those of the built-in and third-party applications, you make it easier for your users to understand how to get their work done in your applications with little risk. This reduces the mental effort they must spend on using the application, and makes it less likely that they will make mistakes in using or configuring it — just as developing with an eye on usability and accessibility helps to provide an easier user experience. Users enjoy being pleasantly surprised by the ease of using your application; they do not enjoy being surprised to find that it’s sharing their information with the world when they thought it was not.

The purpose of this book is twofold. First, I hope to show how we developers of Mac and iPhone applications can reason about the security requirements of our users and the risks to which our applications are exposed. Then you can examine the security features and APIs available on the Mac and iPhone platforms in the context of that fresh understanding of your apps, to see how to reduce risks and provide your customers with a secure experience.

Who Should Read This Book

This book is for Cocoa and Cocoa Touch developers who are interested in ensuring that their applications provide a secure experience. You do not need any experience or familiarity with security principles or secure application development. I do assume that you are comfortable with the C and Objective-C languages, and familiar enough with the APIs that the discussions of code samples can focus on the aspect directly relevant to the matter at hand.

Perhaps you’re reading this thinking, “But my app is so small, and doesn’t have anything of value, so why would hackers target me”? First, disabuse yourself of the idea that all security risks come from pimply teenagers “hacking” their way into important computers from their parents’ basements. The attacker could easily be an otherwise legitimate user of your app who has found a way to subvert it for his or her own needs, whether to craft a fake high-score entry for an online game or to read documents to which the user should not have access. The attack could even be entirely accidental: a user who mistakenly deletes critical data from an application has unintentionally exploited a weakness in that application. These possibilities will be explored throughout the rest of the book.

Nonetheless, consider the accuracy of the traditional view of the hacker. Is this person trying to compromise your app specifically? Maybe, if the purpose is to show that some competitor’s app is a better choice. The attacker could have some other target in mind, for which your application provides a convenient stepping stone. Perhaps the idea is to get a document from a user who also has your application installed. Maybe your app uses some web service such as a social networking site, and it’s that site the hacker is targeting. Maybe the hacker just wants to show that a Mac (or iPhone) can be compromised, and any application is fair game in proving that point. In January 2007, a project known as the “Month of Apple Bugs” (http://projects.info-pull.com/moab/) was launched, with the aim of publicizing security problems on the Mac platform. A large fraction of the vulnerabilities reported in that month did not affect Mac OS X itself, or even Apple’s software, but third-party applications that run on the Mac platform. You have to agree with Michael Howard and David LeBlanc, who in their book Writing Secure Code said, “The defender must defend all points; the attacker can choose the weakest point.” The security profile of a user’s system depends on the concerted efforts of all the developers who write all the apps the user relies on.

What Are We Trying to Secure, and from What?

The first chapter of this book provides an overview of the security considerations to take into account when designing an application. Its message can easily be distilled into one sentence: know your app and its users. There, that’s it; you can stop reading now (though I still recommend you buy the whole book because the wordy version is more interesting, I promise you that much). Without an understanding of what your users are trying to get done, whom they’re communicating with to get it done, and how they’re communicating, you cannot possibly know which security techniques are relevant to your application. Time you spend on adding irrelevant security countermeasures is time (and money) wasted with no valuable return — imagine building the Great Wall today to protect China from an enemy armed with cruise missiles.

In fact you can even do worse than build irrelevant countermeasures — you can build ones that stop your users from getting their work done. Increasingly, modern applications experience the challenge of flexibility vs. security. As we interact in a more connected world, the balance of these two objectives is being stressed more each day. There’s a cliché in the security world that the most secure computer is one that is disconnected from the power supply, encased in a concrete block, and sunk to the bottom of an ocean. That’s great, but how do I check my mail on it? If the reason I want a computer is to check my mail, and I can’t, then the so-called security is actively working against me. I’ll choose a different computer that doesn’t have that “protection,” and the person who poured the concrete has lost a sale.

The point of this story is that there is no such thing as a “most secure” or “perfectly secure” system or application. Many are appropriately secure, and even more could be made appropriately secure with very little effort correctly applied. This book is intended to help you decide what is appropriately secure for your users, and then how to use the tools at your disposal to achieve that security. Appropriate security means that you provide a reasonably risk-free user experience; you do not stop the user at every turn with a password prompt to keep the bad guys out. While this book will help you reason about the security model of your application, it cannot possibly be a substitute for performing that reasoning yourself. Turning to the last code sample now and typing the example source into your app will not add security pixie dust to the app; unfortunately, the security pixies do not exist (though I expect one of the anti-virus vendors might use them in its marketing someday).

By knowing what the users (and, of course, the attackers) want to do, you can easily identify the most important risks to the application. You can then work to mitigate just those risks — a wise and fruitful investment in your application’s development. Some of the risks you find may be reduced by a different application design. Others may be mitigated by your taking advantage of Mac OS X or iPhone OS security features; this is the focus of Chapters 2 through 8. Still others may require careful coding to avoid buffer overruns or the mishandling of incoming data, which is addressed in Chapter 9.

Of course you will want to choose a point where sufficient, but not excessive, energy and time have been spent on the application and it is ready to ship. Security is no different from features, graphics, or bug fixes in this regard: put in too much time and the returns will decrease, all the while giving your competitors more time to ship their apps. Chapter 10 describes the security implications of shipping software, including security documentation, and handling any security issues that arise in the field.

Finally, Chapter 11 takes a brief tour through the world of Mac OS X kernel extensions. Kernel code operates in a significantly different environment from application code; it is important to understand this environment to produce secure kernel extensions.

About the Examples

I hope you can tell that I believe the security considerations of app developers are highly dependent on the applications they are writing, and the environments and contexts within which their users operate. With that in mind, please take the code samples in this book in the spirit in which they are intended — as examples of using a particular API to achieve certain goals, rather than recipes to be pasted verbatim into other applications.

It may be that the risk addressed by one of the code samples is not one your application faces, so the effect of integrating the example would be to spend time and effort without any meaningful result. Worse, indiscriminately applying sample code to your application could increase some risks. For example, if you require authorization to enable some security feature (see Chapter 6 on performing privileged tasks), then it is harder for non-administrator users to enable that feature. Conversely, providing access to the feature to all comers might lead to a privilege escalation vulnerability — a problem discussed in Chapter 1. The only way to resolve the conflict is to weigh the importance of each risk — something that depends strongly on the specifics of your application. Of course, should you decide that the threat countered in the sample is one you need to address, feel free to use the code and techniques in the examples in your own application.

Conventions Used in This Book

To help you get the most from the text and keep track of what’s happening, we’ve used some conventions throughout the book. Typical examples follow:

Notes, tips, hints, tricks, and asides to the current discussion are offset and placed in italics like this.

A warning tells you that something terrible will happen should a particular event occur. For example, if you perform a task incorrectly, you might see data loss.

As for styles in the text:

We italicize new terms and important words when we introduce them.

We show keyboard strokes like this: Ctrl+A.

We show filenames, URLs, and code within the text like so: persistence.properties.

We present code in the following way:

We use a monofont type with no highlighting for most code examples.

Source Code

As you work through the examples in this book, you may choose either to type in all the code manually, or to use the source code files that accompany the book. All the source code used in this book is available for download at http://www.wrox.com. When at the site, simply locate the book’s title (use the Search box or one of the title lists) and click the Download Code link on the book’s detail page to obtain all the source code for the book. Code that is included on the web site is highlighted by the following icon:

Listings include the filename in the title. If it is just a code snippet, you’ll find the filename in a code note such as this:

Code snippet filename

Because many books have similar titles, you may find it easiest to search by ISBN; this book’s ISBN is 978-0-470-52595-1.

Once you download the code, just decompress it with your favorite compression tool. Alternately, you can go to the main Wrox code download page at http://www.wrox.com/dynamic/books/download.aspx to see the code available for this book and all other Wrox books.

Errata

We make every effort to ensure that there are no errors in the text or in the code. However, no one is perfect, and mistakes do occur. If you find an error in one of our books, like a spelling mistake or faulty piece of code, we would be very grateful for your feedback. By sending in errata you may save another reader hours of frustration and at the same time you will be helping us provide even higher quality information.

To find the errata page for this book, go to http://www.wrox.com and locate the title using the Search box or one of the title lists. Then, on the Book Search Results page, click the Errata link. On this page you can view all errata that has been submitted for this book and posted by Wrox editors.

A complete book list including links to each book’s errata is also available at www.wrox.com/misc-pages/booklist.shtml.

If you don’t spot “your” error on the Errata page, click the Errata Form link and complete the form to send us the error you have found. We’ll check the information and, if appropriate, post a message to the book’s errata page and fix the problem in subsequent editions of the book.

p2p.wrox.com

For author and peer discussion, join the P2P forums at p2p.wrox.com. The forums are a Web-based system for you to post messages relating to Wrox books and related technologies and interact with other readers and technology users. The forums offer a subscription feature to e-mail you topics of interest of your choosing when new posts are made to the forums. Wrox authors, editors, other industry experts, and your fellow readers are present on these forums.

At http://p2p.wrox.com you will find a number of different forums that will help you not only as you read this book, but also as you develop your own applications. To join the forums, just follow these steps:

1. Go to p2p.wrox.com and click the Register link.

2. Read the terms of use and click Agree.

3. Complete the required information to join as well as any optional information you wish to provide, and click Submit.

4. You will receive an e-mail with information describing how to verify your account and complete the joining process.

You can read messages in the forums without joining P2P but in order to post your own messages, you must join.

Once you join, you can post new messages and respond to messages other users post. You can read messages at any time on the Web. If you would like to have new messages from a particular forum e-mailed to you, click the Subscribe to This Forum icon by the forum name in the forum listing.

For more information about how to use the Wrox P2P, be sure to read the P2P FAQs for answers to questions about how the forum software works as well as many common questions specific to P2P and Wrox books. To read the FAQs, click the FAQ link on any P2P page.

Chapter 1: Secure by Design

WHAT’S IN THIS CHAPTER?

Understanding your application’s security needs

Discovering the threats to your users

Identifying potential vulnerabilities

As with any other class of bug, addressing a security issue becomes more expensive the longer you wait to fix it. If there’s a problem in the design of the application, trying to fix it in a bugfix release will be very costly because you’ll need to change multiple classes. You’ll also need to understand and account for the myriad uses and configurations your customers have in place, and be ready to support migration of all these to the new, fixed version of the application. Addressing the issue the first time around means not only spending less time on the issue, but also avoiding the additional (direct and indirect) costs of a security vulnerability out in the field and coordinating a fix release. I once worked on a project for which we spent about three weeks addressing an issue that had been caused by a bad choice of file system path in the planning phase, some years earlier.

Of course it’s not going to be possible or even desirable to identify and fix every single vulnerability before writing any code. That’s a recipe for spending a great deal of money and taking a very long time to get to market, by which time your competitors will have gotten their apps to the customers. There is a principle software engineers have borrowed from economics called the Pareto Principle, also known as the “80/20 rule.” The principle says that 80 percent of the observable effects in any situation are often the result of only 20 percent of the causes. It’s a good idea to follow the 80/20 rule in software design — addressing only the most important issues so that the product is of a high enough quality to ship. Which of course leads us to the question, “Which are the important issues?”

About Cocoa Security

Users of your application do not think about what technology was used to create it — whether it was written in Cocoa, Carbon, or Java. What they care about is using the app on their iPhones or their Macs to get their work done. Similarly, their concerns regarding security come not from Cocoa-specific features or issues, but from how the application’s security helps or hinders them in doing their work (or, in the case of a game, in having their fun). Your model of the important security considerations in your app will therefore be largely technology-agnostic, although there are vulnerabilities specific to Objective-C and Cocoa, as discussed in Chapter 9, “Writing Secure Application Code.”

The particular capabilities and APIs available in Cocoa and Cocoa Touch applications become more relevant when you determine how some of the threats you identify might be exploited by an attacker. Cocoa applications on the Mac are part of a multi-user system, as explained in Chapter 2, “Managing Multiple Users,” so understanding how the different users can interact through inter-process communication or by sharing files on the file system will help you decide whether particular interactions could lead to one user’s threatening the security of another. Prioritizing security issues will always be based on an understanding of what your users are trying to do and how that fits in with their processes and with the environment.

You must also have Cocoa-specific features and technology in mind when deciding how to mitigate the threats that attackers may be posing to your application and its users. Users will expect your app to behave in the same way as others on the Mac or iPhone platform, which can be easily achieved if you adopt the frameworks Apple provides for the purpose. As an example, if your application stores a user’s password, he will expect it to use the keychain to do so, because then he can change the settings for that password in the same way as for all his other applications. Keychain Services are described in Chapter 5, “Storing Confidential Information with the Keychain.”

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!